ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-12-29 22:15:04
Exec Total Coverage
Lines: 99 7515 1.3%
Functions: 1 191 0.5%
Branches: 14 6857 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "allegro/color.h"
5 #include "base/files.h"
6 #include "base/pal_tables.h"
7 #include "base/qrs.h"
8 #include "base/dmap.h"
9 #include "base/cpool.h"
10 #include "base/autocombo.h"
11 #include "base/packfile.h"
12 #include "base/gui.h"
13 #include "base/combo.h"
14 #include "base/msgstr.h"
15 #include "base/zdefs.h"
16 #include "new_subscr.h"
17 #include "subscr.h"
18 #include "zq/zq_tiles.h"
19 #include "zq/zquest.h"
20 #include "tiles.h"
21 #include "zq/zq_misc.h"
22 #include "zq/zq_class.h"
23 #include "base/zsys.h"
24 #include "base/colors.h"
25 #include "base/qst.h"
26 #include "gui/jwin.h"
27 #include <base/new_menu.h>
28 #include "base/jwinfsel.h"
29 #include "hero_tiles.h"
30 #include "zq/questReport.h"
31 #include "dialog/info.h"
32 #include "dialog/scaletile.h"
33 #include "dialog/rotatetile.h"
34 #include "drawing.h"
35 #include "colorname.h"
36 #include "zq/render.h"
37 #include "zinfo.h"
38 #include <fmt/format.h>
39 #include <functional>
40 #include "zq/moveinfo.h"
41 using std::set;
42
43
44 #ifdef _MSC_VER
45 #define stricmp _stricmp
46 #endif
47
48 #define HIDE_USED (show_only_unused_tiles&1)
49 #define HIDE_UNUSED (show_only_unused_tiles&2)
50 #define HIDE_BLANK (show_only_unused_tiles&4)
51 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
52
53 extern void large_dialog(DIALOG *d);
54 static void massRecolorReset4Bit();
55 static void massRecolorReset8Bit();
56 static bool massRecolorSetup(int32_t cset);
57 static void massRecolorApply(int32_t tile);
58 extern int32_t last_droplist_sel;
59 extern int32_t TilePgCursorCol, CmbPgCursorCol;
60
61 int32_t ex=0;
62 int32_t nextcombo_fake_click=0;
63 int32_t invcol=0;
64 int32_t tthighlight = 1;
65 int32_t showcolortip = 1;
66 int32_t show_quartgrid = 0, hide_grid = 0;
67
68 tiledata *newundotilebuf;
69 std::vector<newcombo> undocombobuf;
70
71 BITMAP *selection_pattern;
72 byte selection_grid[18][18];
73 byte selection_anchor=0;
74
75 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
76 BITMAP *selecting_pattern;
77 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
78
79 BITMAP *intersection_pattern;
80
81 byte relational_template[48][4]=
82 {
83 { 0, 0, 0, 0 },
84 { 0, 1, 0, 0 },
85 { 1, 0, 0, 0 },
86 { 1, 1, 0, 0 },
87 { 0, 0, 1, 0 },
88 { 0, 1, 1, 0 },
89 { 1, 0, 1, 0 },
90 { 1, 1, 1, 0 },
91 { 0, 0, 0, 1 },
92 { 0, 1, 0, 1 },
93 { 1, 0, 0, 1 },
94 { 1, 1, 0, 1 },
95 { 0, 0, 1, 1 },
96 { 0, 1, 1, 1 },
97 { 1, 0, 1, 1 },
98 { 1, 1, 1, 1 },
99 { 0, 2, 0, 2 },
100 { 1, 2, 0, 2 },
101 { 0, 2, 1, 2 },
102 { 1, 2, 1, 2 },
103 { 3, 3, 0, 0 },
104 { 3, 3, 1, 0 },
105 { 3, 3, 0, 1 },
106 { 3, 3, 1, 1 },
107 { 3, 4, 0, 2 },
108 { 3, 4, 1, 2 },
109 { 2, 0, 2, 0 },
110 { 2, 1, 2, 0 },
111 { 2, 0, 2, 1 },
112 { 2, 1, 2, 1 },
113 { 2, 2, 2, 2 },
114 { 4, 3, 2, 0 },
115 { 4, 3, 2, 1 },
116 { 4, 4, 2, 2 },
117 { 0, 0, 3, 3 },
118 { 0, 1, 3, 3 },
119 { 1, 0, 3, 3 },
120 { 1, 1, 3, 3 },
121 { 0, 2, 3, 4 },
122 { 1, 2, 3, 4 },
123 { 3, 3, 3, 3 },
124 { 3, 4, 3, 4 },
125 { 2, 0, 4, 3 },
126 { 2, 1, 4, 3 },
127 { 2, 2, 4, 4 },
128 { 4, 3, 4, 3 },
129 { 4, 4, 4, 4 },
130 { 5, 5, 5, 5 }
131 };
132
133 byte dungeon_carving_template[96][4]=
134 {
135 { 0, 0, 0, 0 },
136 { 0, 1, 0, 0 },
137 { 1, 0, 0, 0 },
138 { 1, 1, 0, 0 },
139 { 0, 0, 1, 0 },
140 { 0, 1, 1, 0 },
141 { 1, 0, 1, 0 },
142 { 1, 1, 1, 0 },
143 { 0, 0, 0, 1 },
144 { 0, 1, 0, 1 },
145 { 1, 0, 0, 1 },
146 { 1, 1, 0, 1 },
147 { 0, 0, 1, 1 },
148 { 0, 1, 1, 1 },
149 { 1, 0, 1, 1 },
150 { 1, 1, 1, 1 },
151 { 0, 2, 0, 2 },
152 { 1, 2, 0, 2 },
153 { 0, 2, 1, 2 },
154 { 1, 2, 1, 2 },
155 { 3, 3, 0, 0 },
156 { 3, 3, 1, 0 },
157 { 3, 3, 0, 1 },
158 { 3, 3, 1, 1 },
159 { 3, 4, 0, 2 },
160 { 3, 4, 1, 2 },
161 { 2, 0, 2, 0 },
162 { 2, 1, 2, 0 },
163 { 2, 0, 2, 1 },
164 { 2, 1, 2, 1 },
165 { 2, 2, 2, 2 },
166 { 4, 3, 2, 0 },
167 { 4, 3, 2, 1 },
168 { 4, 4, 2, 2 },
169 { 0, 0, 3, 3 },
170 { 0, 1, 3, 3 },
171 { 1, 0, 3, 3 },
172 { 1, 1, 3, 3 },
173 { 0, 2, 3, 4 },
174 { 1, 2, 3, 4 },
175 { 3, 3, 3, 3 },
176 { 3, 4, 3, 4 },
177 { 2, 0, 4, 3 },
178 { 2, 1, 4, 3 },
179 { 2, 2, 4, 4 },
180 { 4, 3, 4, 3 },
181 { 4, 4, 4, 4 },
182 { 5, 5, 5, 5 },
183
184 { 5, 5, 5, 5 },
185 { 6, 6, 6, 6 },
186 { 7, 7, 7, 7 },
187 { 7, 6, 7, 6 },
188 { 8, 8, 8, 8 },
189 { 16, 6, 8, 15 },
190 { 7, 7, 8, 8 },
191 { 7, 6, 8, 15 },
192 { 9, 9, 9, 9 },
193 { 6, 6, 9, 9 },
194 { 7, 17, 14, 9 },
195 { 7, 6, 14, 9 },
196 { 8, 9, 8, 9 },
197 { 16, 6, 8, 9 },
198 { 7, 17, 8, 9 },
199 { 7, 6, 8, 9 },
200 { 10, 10, 10, 10 },
201 { 7, 10, 14, 10 },
202 { 16, 10, 8, 10 },
203 { 7, 10, 8, 10 },
204 { 11, 11, 11, 11 },
205 { 11, 11, 8, 15 },
206 { 11, 11, 14, 9 },
207 { 11, 11, 8, 9 },
208 { 14, 14, 14, 14 },
209 { 14, 14, 8, 14 },
210 { 12, 12, 12, 12 },
211 { 12, 6, 12, 15 },
212 { 12, 17, 12, 9 },
213 { 12, 6, 12, 9 },
214 { 12, 10, 12, 10 },
215 { 15, 15, 15, 15 },
216 { 15, 15, 15, 9 },
217 { 15, 14, 12, 10 },
218 { 13, 13, 13, 13 },
219 { 16, 6, 13, 13 },
220 { 7, 17, 13, 13 },
221 { 7, 6, 13, 13 },
222 { 16, 16, 16, 16 },
223 { 7, 16, 16, 16 },
224 { 11, 11, 13, 13 },
225 { 11, 14, 13, 16 },
226 { 17, 17, 17, 17 },
227 { 17, 6, 17, 17 },
228 { 12, 10, 17, 16 },
229 { 15, 11, 17, 13 },
230 { 15, 14, 17, 16 },
231 { 18, 18, 18, 18 }
232 };
233
234 struct tile_move_data
235 {
236 int32_t copies;
237 int32_t dest_first;
238 int32_t dest_last;
239 int32_t src_first;
240 int32_t src_last;
241 int32_t dest_top;
242 int32_t dest_bottom;
243 int32_t src_top;
244 int32_t src_bottom;
245 int32_t src_left, src_right;
246 int32_t src_width, src_height;
247 int32_t dest_left, dest_right;
248 int32_t dest_width, dest_height;
249 int32_t rows, cols;
250 bool rect, move;
251
252 tile_move_data()
253 {
254 copies = dest_first = dest_last = src_first = src_last = dest_top =
255 dest_bottom = src_top = src_bottom = src_left = src_right =
256 src_width = src_height = dest_left = dest_right = dest_width =
257 dest_height = rows = cols = 0;
258 rect = move = false;
259 }
260
261 tile_move_data(tile_move_data const& other)
262 {
263 copy(other);
264 }
265
266 tile_move_data& operator=(tile_move_data const& other)
267 {
268 copy(other);
269 return *this;
270 }
271
272 void copy(tile_move_data const& other)
273 {
274 copies = other.copies;
275 dest_first = other.dest_first;
276 dest_last = other.dest_last;
277 src_first = other.src_first;
278 src_last = other.src_last;
279 dest_top = other.dest_top;
280 dest_bottom = other.dest_bottom;
281 src_top = other.src_top;
282 src_bottom = other.src_bottom;
283 src_left = other.src_left;
284 src_right = other.src_right;
285 src_width = other.src_width;
286 src_height = other.src_height;
287 dest_left = other.dest_left;
288 dest_right = other.dest_right;
289 dest_width = other.dest_width;
290 dest_height = other.dest_height;
291 rows = other.rows;
292 cols = other.cols;
293 rect = other.rect;
294 move = other.move;
295 }
296
297 void flip()
298 {
299 zc_swap(src_first, dest_first);
300 zc_swap(src_last, dest_last);
301 zc_swap(src_top, dest_top);
302 zc_swap(src_bottom, dest_bottom);
303 zc_swap(src_left, dest_left);
304 zc_swap(src_right, dest_right);
305 zc_swap(src_width, dest_width);
306 zc_swap(src_height, dest_height);
307 }
308 };
309 bool do_movetile_united(tile_move_data const& tmd);
310
311 struct combo_move_data
312 {
313 int32_t tile, tile2, copy1, copycnt;
314 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
315 combo_move_data(combo_move_data const& other)
316 {
317 copy(other);
318 }
319 combo_move_data& operator=(combo_move_data const& other)
320 {
321 copy(other);
322 return *this;
323 }
324 void copy(combo_move_data const& other)
325 {
326 tile = other.tile;
327 tile2 = other.tile2;
328 copy1 = other.copy1;
329 copycnt = other.copycnt;
330 }
331
332 void flip()
333 {
334 int32_t tcnt = tile2-tile+1;
335 int32_t cpy2 = copy1+copycnt-1;
336 zc_swap(tile,copy1);
337 tile2 = cpy2;
338 copycnt = tcnt;
339 }
340 };
341
342 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
343 static optional<ComboMoveUndo> last_combo_move_list;
344 static optional<TileMoveUndo> last_tile_move_list;
345
346 int refl_flags = 0;
347 enum
348 {
349 REFL_90CW, REFL_HFLIP,
350 REFL_90CCW, REFL_VFLIP,
351 REFL_180, REFL_DBLFLIP,
352 REFL_MAX
353 };
354 const char *reflbtn_names[] =
355 {
356 "90 CW", "HFlip",
357 "90 CCW", "VFlip",
358 "180 Rot", "Diag Flip"
359 };
360 int bgmode = 0, xmode = 0;
361 const char *bgmodebtn_names[] =
362 {
363 "BG Color 0", "BG Trans."
364 };
365 const char *xmodebtn_names[] =
366 {
367 "X", "No X"
368 };
369 enum
370 {
371 XMODE_X, XMODE_NOX,
372 XMODE_MAX
373 };
374 enum
375 {
376 BGMODE_0, BGMODE_TRANSP,
377 BGMODE_MAX
378 };
379
380 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
381 {
382 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
383 int32_t size2=size>>1;
384
385 if(newtilebuf[dest_tile].data==NULL)
386 {
387 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
388 }
389
390 int32_t i=0;
391
392 if((dest_tile<<2)+i!=src_quarter1)
393 {
394 for(int32_t j=0; j<8; ++j)
395 {
396 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
397 }
398 }
399
400 i=1;
401
402 if((dest_tile<<2)+i!=src_quarter2)
403 {
404 for(int32_t j=0; j<8; ++j)
405 {
406 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
407 }
408 }
409
410 i=2;
411
412 if((dest_tile<<2)+i!=src_quarter3)
413 {
414 for(int32_t j=0; j<8; ++j)
415 {
416 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
417 }
418 }
419
420 i=3;
421
422 if((dest_tile<<2)+i!=src_quarter4)
423 {
424 for(int32_t j=0; j<8; ++j)
425 {
426 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
427 }
428 }
429 }
430
431 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
432 {
433 al_trace("inside make_combos()\n");
434 int32_t startCombo=0;
435
436 if(!select_combo_2(startCombo,cs))
437 return;
438
439 int32_t temp=combobuf[startCombo].o_tile;
440 combobuf[startCombo].set_tile(startTile);
441
442 if(!edit_combo(startCombo, false, cs))
443 {
444 combobuf[startCombo].set_tile(temp);
445 return;
446 }
447
448 go_combos();
449
450 for(int32_t i=0; i<=endTile-startTile; i++)
451 {
452 combobuf[startCombo+i]=combobuf[startCombo];
453 combobuf[startCombo+i].set_tile(startTile+i);
454 }
455
456 setup_combo_animations();
457 setup_combo_animations2();
458 }
459
460 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
461 {
462 int32_t startCombo=0;
463
464 if(!select_combo_2(startCombo, cs))
465 return;
466
467 int32_t startTile=top*TILES_PER_ROW+left;
468 int32_t temp=combobuf[startCombo].o_tile;
469 combobuf[startCombo].set_tile(startTile);
470
471 if(!edit_combo(startCombo, false, cs))
472 {
473 al_trace("make_combos_rect() early return\n");
474 combobuf[startCombo].set_tile(temp);
475 return;
476 }
477
478 bool smartWrap=false;
479 if(numCols!=4 && numRows>1)
480 {
481 char buf[64];
482 if(numCols<4)
483 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
484 else
485 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
486 if (alert_confirm("Wrapping", buf))
487 smartWrap=true;
488 }
489
490 go_combos();
491
492 int32_t combo=startCombo-1;
493 for(int32_t row=0; row<numRows; row++)
494 {
495 for(int32_t col=0; col<numCols; col++)
496 {
497 int32_t tile=startTile+row*TILES_PER_ROW+col;
498 if(smartWrap)
499 // Add 4 per row, and another numRows*4 for every 4 columns
500 // (col&0xFC==col/4*4), and then the column %4
501 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
502 else
503 combo++;
504
505 combobuf[combo]=combobuf[startCombo];
506 combobuf[combo].set_tile(tile);
507 }
508 }
509
510 setup_combo_animations();
511 setup_combo_animations2();
512 }
513
514 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
515
516 static bool nogotiles = false;
517 static bool nogocombos = false;
518
519 void go_tiles()
520 {
521 if(nogotiles) return;
522 last_tile_move_list = nullopt;
523 for(int32_t i=0; i<NEWMAXTILES; ++i)
524 {
525 newundotilebuf[i].format=newtilebuf[i].format;
526
527 if(newundotilebuf[i].data!=NULL)
528 {
529 free(newundotilebuf[i].data);
530 }
531
532 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
533
534 if(newundotilebuf[i].data==NULL)
535 {
536 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
537 }
538
539 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
540 }
541 }
542
543 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
544 {
545 for(int32_t c=0; c<columns; c++)
546 {
547 for(int32_t r=0; r<rows; r++)
548 {
549 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
550 newundotilebuf[t].format=newtilebuf[t].format;
551
552 if(newundotilebuf[t].data!=NULL)
553 {
554 free(newundotilebuf[t].data);
555 }
556
557 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
558
559 if(newundotilebuf[t].data==NULL)
560 {
561 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
562 }
563
564 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
565 }
566 }
567 }
568
569 void comeback_tiles()
570 {
571 if(last_tile_move_list)
572 {
573 last_tile_move_list->undo();
574 last_tile_move_list = nullopt;
575 }
576 for(dword i=0; i<NEWMAXTILES; ++i)
577 {
578 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
579 {
580 newtilebuf[i].format = newundotilebuf[i].format;
581
582 if(newtilebuf[i].data!=NULL)
583 free(newtilebuf[i].data);
584 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
585 if(newtilebuf[i].data==NULL)
586 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
587 }
588
589 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
590 }
591
592 register_blank_tiles();
593 register_used_tiles();
594 }
595
596 void go_combos()
597 {
598 if(nogocombos) return;
599 last_combo_move_list = nullopt;
600
601 undocombobuf = combobuf;
602 }
603
604 void comeback_combos()
605 {
606 if(last_combo_move_list)
607 {
608 last_combo_move_list->undo();
609 last_combo_move_list = nullopt;
610 }
611
612 combobuf = undocombobuf;
613 }
614
615 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
616 {
617 line(dest,x,y,x+s,y+s,c);
618 line(dest,x+s,y,x,y+s,c);
619 }
620 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
621 {
622 line(dest,x,y,x+w,y+h,c);
623 line(dest,x+w,y,x,y+h,c);
624 }
625
626 enum {gm_light, gm_dark, gm_max};
627 int32_t gridmode=gm_light;
628
629 bool has_selection()
630 {
631 for(int32_t i=1; i<17; ++i)
632 {
633 for(int32_t j=1; j<17; ++j)
634 {
635 if(selection_grid[i][j])
636 {
637 return true;
638 }
639 }
640 }
641
642 return false;
643 }
644
645 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
646 {
647 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
648
649 for(int32_t i=1; i<18; ++i)
650 {
651 for(int32_t j=1; j<18; ++j)
652 {
653 // zoomtile16(screen2,tile,79,31,cs,flip,8);
654 if(selection_grid[i-1][j]!=selection_grid[i][j])
655 {
656 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
657 }
658
659 if(selection_grid[i][j-1]!=selection_grid[i][j])
660 {
661 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
662 }
663 }
664 }
665
666 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
667 // selection_anchor=(selection_anchor+1)%64;
668 }
669
670 bool is_selecting()
671 {
672 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
673 }
674
675 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
676 {
677 int32_t x1=zc_min(selecting_x1,selecting_x2);
678 int32_t x2=zc_max(selecting_x1,selecting_x2);
679 int32_t y1=zc_min(selecting_y1,selecting_y2);
680 int32_t y2=zc_max(selecting_y1,selecting_y2);
681
682 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
683 for(int32_t i=1; i<18; ++i)
684 {
685 for(int32_t j=1; j<18; ++j)
686 {
687 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
688
689 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
690 {
691 if(selection_grid[i-1][j]!=selection_grid[i][j])
692 {
693 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
694 }
695
696 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
697 }
698
699 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
700 {
701 if(selection_grid[i][j-1]!=selection_grid[i][j])
702 {
703 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
704 }
705
706 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
707 }
708 }
709 }
710
711 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
712 // selection_anchor=(selection_anchor+1)%64;
713 }
714
715 void unfloat_selection();
716 bool floating_sel = false;
717 byte floatsel[256];
718 byte undofloatsel[256];
719 bool undo_is_floatsel = false;
720
721
722 void add_color_to_selection(int32_t color)
723 {
724 unfloat_selection();
725 for(int32_t i=1; i<17; ++i)
726 {
727 for(int32_t j=1; j<17; ++j)
728 {
729 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
730 {
731 selection_grid[i][j]=1;
732 }
733 }
734 }
735 }
736
737 void remove_color_from_selection(int32_t color)
738 {
739 unfloat_selection();
740 for(int32_t i=1; i<17; ++i)
741 {
742 for(int32_t j=1; j<17; ++j)
743 {
744 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
745 {
746 selection_grid[i][j]=0;
747 }
748 }
749 }
750 }
751
752 void intersect_color_with_selection(int32_t color)
753 {
754 unfloat_selection();
755 for(int32_t i=1; i<17; ++i)
756 {
757 for(int32_t j=1; j<17; ++j)
758 {
759 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
760 {
761 selection_grid[i][j]=1;
762 }
763 else
764 {
765 selection_grid[i][j]=0;
766 }
767 }
768 }
769 }
770
771 bool is_in_selection(int32_t x, int32_t y)
772 {
773 x %= 16; y %= 16;
774 if(x < 0) x = (16 - abs(x));
775 if(y < 0) y = (16 - abs(y));
776 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
777 }
778
779 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
780 {
781 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
782 int gridcol = gridmode==gm_light?vc(7):vc(8);
783
784 cset <<= 4;
785 if(newtilebuf[tile].format>tf4Bit)
786 cset=0;
787
788 int g = hide_grid ? 1 : 0;
789 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
790 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
791
792 unpack_tile(newtilebuf, tile, 0, false);
793 byte *si = unpackbuf;
794 for(int32_t cy=0; cy<16; cy++)
795 {
796 for(int32_t cx=0; cx<16; cx++)
797 {
798 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
799 int32_t dx = ((flip&1)?15-cx:cx)*m;
800 int32_t dy = ((flip&2)?15-cy:cy)*m;
801 if(col)
802 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
803
804 if(!col && xmode == XMODE_X)
805 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
806
807 ++si;
808 }
809 }
810
811 if(!hide_grid)
812 {
813 for(int cx = 0; cx <= 16; ++cx)
814 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
815 for(int cy = 0; cy <= 16; ++cy)
816 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
817 }
818
819 if(show_quartgrid)
820 {
821 int offs = (8*m);
822 const int RAD = 3;
823 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
824 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
825 }
826
827 if(has_selection()||is_selecting())
828 {
829 selection_anchor=(selection_anchor+1)%64;
830
831 if(has_selection()||is_selecting())
832 draw_selection_outline(dest, x, y, m);
833
834 if(is_selecting())
835 draw_selecting_outline(dest, x, y, m);
836 }
837 }
838
839 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
840 {
841 if(!jwin)
842 {
843 if(flags&D_SELECTED)
844 {
845 zc_swap(fg,bg);
846 }
847
848 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
849 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
850 rect(dest,x,y,x+w-2,y+h-2,fg);
851 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
852 }
853 else
854 {
855 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
856 }
857 }
858
859 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
860 {
861 if(!jwin)
862 {
863 if(flags&D_SELECTED)
864 {
865 zc_swap(fg,bg);
866 }
867
868 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
869 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
870 rect(dest,x,y,x+w-2,y+h-2,fg);
871 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
872 }
873 else
874 {
875 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
876 }
877 }
878
879 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
880 {
881 if(flags&D_SELECTED)
882 {
883 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
884 ++x;
885 ++y;
886 --w;
887 --h;
888 }
889 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
890 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
891
892 //Forcibly fit the text within the button
893 char buf[512] = {0};
894 strcpy(buf, text);
895
896 bool dis = (flags&D_DISABLED);
897 auto hei = text_height(font);
898 auto len = text_length(font,buf);
899 auto borderwid = 8;
900 if(len > w - borderwid + (dis ? 1 : 0))
901 {
902 auto ind = strlen(buf) - 1;
903 auto dotcount = 0;
904 while(len > w - borderwid + (dis ? 1 : 0))
905 {
906 if(dotcount >= 2)
907 buf[ind+2] = 0;
908 else ++dotcount;
909 buf[ind--] = '.';
910 len = text_length(font,buf);
911 }
912 }
913 if(dis)
914 {
915 ++len; ++hei;
916 }
917 BITMAP* tmp = create_bitmap_ex(8,len,hei);
918 clear_bitmap(tmp);
919 if(dis)
920 {
921 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
922 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
923 }
924 else
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
926 auto tx = x+((w-len)/2);
927 auto ty = y+((h-hei)/2);
928 if(len > w-borderwid)
929 {
930 tx = x+borderwid/2;
931 len = w-borderwid;
932 }
933 if(hei > h-borderwid)
934 {
935 ty = y+borderwid/2;
936 hei = h-borderwid;
937 }
938 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
939 destroy_bitmap(tmp);
940 }
941
942 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
943 {
944 bool over=false;
945
946 while(gui_mouse_b())
947 {
948 //vsync();
949 if(mouse_in_rect(x,y,w,h))
950 {
951 if(!over)
952 {
953 vsync();
954 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
955 over=true;
956
957 update_hw_screen();
958 }
959 }
960 else
961 {
962 if(over)
963 {
964 vsync();
965 draw_layer_button(screen, x, y, w, h, text, flags);
966 over=false;
967
968 update_hw_screen();
969 }
970 }
971 //rest(1);
972 }
973
974 if(over)
975 {
976 vsync();
977 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
978
979 update_hw_screen();
980 }
981
982 return over;
983 }
984
985 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
986 {
987 bool over=false;
988
989 while(gui_mouse_b())
990 {
991 custom_vsync();
992
993 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
994 {
995 if(!over)
996 {
997 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
998 over=true;
999 }
1000 }
1001 else
1002 {
1003 if(over)
1004 {
1005 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1006 over=false;
1007 }
1008 }
1009 }
1010
1011 if(over)
1012 {
1013 custom_vsync();
1014 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1015 }
1016
1017 return over;
1018 }
1019
1020 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1021 {
1022 if(!jwin)
1023 {
1024 if(flags&D_SELECTED)
1025 {
1026 zc_swap(fg,bg);
1027 }
1028
1029 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1030 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1031 rect(dest,x,y,x+w-2,y+h-2,fg);
1032 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1033
1034 if(overlay)
1035 {
1036 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1037 }
1038 else
1039 {
1040 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1041 }
1042 }
1043 else
1044 {
1045 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1046 }
1047 }
1048
1049 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1050 {
1051 bool over=false;
1052
1053 while(gui_mouse_b())
1054 {
1055 custom_vsync();
1056
1057 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1058 {
1059 if(!over)
1060 {
1061 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1062 over=true;
1063 }
1064 }
1065 else
1066 {
1067 if(over)
1068 {
1069 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1070 over=false;
1071 }
1072 }
1073 }
1074
1075 return over;
1076 }
1077
1078 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1079 {
1080 bool over=false;
1081
1082 while(gui_mouse_b())
1083 {
1084 custom_vsync();
1085
1086 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1087 {
1088 if(!over)
1089 {
1090 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1091 over=true;
1092 }
1093 }
1094 else
1095 {
1096 if(over)
1097 {
1098 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1099 over=false;
1100 }
1101 }
1102 }
1103
1104 if(over)
1105 {
1106 custom_vsync();
1107 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1108 }
1109
1110 return over;
1111 }
1112 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1113 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1114
1115 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1116 {
1117 //these are here to bypass compiler warnings about unused arguments
1118 bg=bg;
1119 fg=fg;
1120
1121 int32_t r, center;
1122
1123 for(int32_t k=0; k<7; k++)
1124 {
1125 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1126 {
1127 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1128 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1129 //*
1130 r = 9/2;
1131
1132 center = x+(k*25)+r;
1133 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1134
1135 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1136 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1137 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1138 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1139 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1140
1141 if(value==k)
1142 {
1143 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1144 }
1145
1146 //*/
1147 }
1148 }
1149 }
1150
1151 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1152 {
1153 while(gui_mouse_b())
1154 {
1155 custom_vsync();
1156
1157 for(int32_t k=0; k<7; k++)
1158 {
1159 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1160 {
1161 //if on radio button
1162 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1163 {
1164 value=k;
1165 draw_layerradio(dest,x,y,bg,fg,value);
1166 refresh(rMENU);
1167 }
1168 }
1169 }
1170 }
1171 }
1172
1173 //*************** tile flood fill stuff **************
1174
1175 byte tf_c;
1176 byte tf_u;
1177
1178 void tile_floodfill_rec(int32_t x,int32_t y)
1179 {
1180 if(is_in_selection(x,y))
1181 {
1182 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1183 --x;
1184
1185 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1186 {
1187 if(is_in_selection(x,y))
1188 {
1189 unpackbuf[(y<<4)+x] = tf_c;
1190 }
1191
1192 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1193 tile_floodfill_rec(x,y-1);
1194
1195 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y+1);
1197
1198 ++x;
1199 }
1200 }
1201 }
1202
1203 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1204 {
1205 if(is_in_selection(x,y))
1206 {
1207 if(floating_sel)
1208 {
1209 memcpy(unpackbuf, floatsel, 256);
1210 }
1211 else unpack_tile(newtilebuf, tile, 0, false);
1212 tf_c = c;
1213 tf_u = unpackbuf[(y<<4)+x];
1214
1215 if(tf_u != tf_c)
1216 tile_floodfill_rec(x,y);
1217 if(floating_sel)
1218 {
1219 memcpy(floatsel, unpackbuf, 256);
1220 }
1221 else pack_tile(newtilebuf,unpackbuf,tile);
1222 }
1223 }
1224
1225 //***************** tile editor stuff *****************
1226 12 size_and_pos ok_button(302,562,71,21);
1227 12 size_and_pos cancel_button(376,562,71,21);
1228 12 size_and_pos edit_button(550,562,86,21);
1229 12 size_and_pos hlcbox(742,392,16,16);
1230 12 size_and_pos hov_prev(742,338,50,50);
1231 12 size_and_pos cpalette_4(648,416,4,4,64,64);
1232 12 size_and_pos cpalette_8(648,416,16,14,16,18);
1233 12 size_and_pos fg_prev(648,316,50,50);
1234 12 size_and_pos bg_prev(648+30,316+30,50,50);
1235 12 size_and_pos zoomtile(124,32,16,16,32,32);
1236 12 size_and_pos prev_til_1(648,31,96,96);
1237 12 size_and_pos prev_til_2(752,31,96,96);
1238 12 size_and_pos prev_til_3(648,135,96,96);
1239 12 size_and_pos prev_til_4(752,135,96,96);
1240 12 size_and_pos ref_til(14,189,96,96);
1241 12 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1242 12 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1243 12 size_and_pos color_info(4,294,1,1,116,8);
1244 12 size_and_pos color_info_btn(24,294,96,21);
1245 12 size_and_pos tool_btns(22,29,2,4,39,39);
1246 12 size_and_pos x_btn(890,5,15,13);
1247 12 size_and_pos info_btn(872,5,15,13);
1248 12 size_and_pos hidegrid_cbox(124,552,16,16);
1249 12 size_and_pos quartgrid_cbox(124,572,16,16);
1250 12 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1251 12 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1252 12 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1253
1254 int32_t c1=1;
1255 int32_t c2=0;
1256 int32_t floating_tile = -1;
1257 int32_t tool = t_pen;
1258 int32_t old_tool = -1;
1259 int32_t tool_cur = -1;
1260 int32_t select_mode = 0;
1261 int32_t drawing=0;
1262 int32_t reftile = 0;
1263
1264 bool qgrid_tool(int tool)
1265 {
1266 switch(tool)
1267 {
1268 case t_pen:
1269 case t_fill:
1270 case t_recolor:
1271 case t_wand:
1272 return true;
1273 }
1274 return false;
1275 }
1276
1277 void set_tool_sprite(int tool, int type)
1278 {
1279 int spr = ZQM_NORMAL;
1280 switch(tool)
1281 {
1282 case t_pen: spr = ZQM_SWORD; break;
1283 case t_fill: spr = ZQM_POTION; break;
1284 case t_recolor: spr = ZQM_WAND; break;
1285 case t_eyedropper: spr = ZQM_LENS; break;
1286 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1287 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1288 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1289 }
1290 MouseSprite::set(spr);
1291 }
1292 void update_tool_cursor()
1293 {
1294 int32_t temp_mouse_x=gui_mouse_x();
1295 int32_t temp_mouse_y=gui_mouse_y();
1296
1297 int32_t type=0;
1298
1299 if(has_selection())
1300 {
1301 switch(tool)
1302 {
1303 case t_select:
1304 case t_wand:
1305 type+=select_mode;
1306 break;
1307 }
1308 }
1309
1310 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1311 {
1312 if(tool_cur==-1)
1313 set_tool_sprite(tool,type);
1314
1315 tool_cur=tool;
1316 }
1317 else if(tool_cur != -1)
1318 {
1319 MouseSprite::set(ZQM_NORMAL);
1320 tool_cur = -1;
1321 }
1322 }
1323
1324 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile,bool create_tbar)
1325 {
1326 PALETTE tpal;
1327 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1328 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1329 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1330
1331 if(!create_tbar)
1332 {
1333 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1334 }
1335 else
1336 {
1337 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1338 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1339 }
1340
1341 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1342
1343 clear_to_color(preview_bmp, 0);
1344
1345 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1346 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1347 puttile16(preview_bmp,tile,0,0,cs,flip);
1348 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1349
1350 clear_to_color(preview_bmp, 0);
1351 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1352 overtile16(preview_bmp,tile,0,0,cs,flip);
1353 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1354 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1355
1356 unpack_tile(newtilebuf, tile, 0, true);
1357 if(floating_sel)
1358 for(auto q = 0; q < 256; ++q)
1359 if(floatsel[q])
1360 unpackbuf[q] = floatsel[q];
1361 byte tmptile[256];
1362 byte *tmpptr = tmptile;
1363 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1364 pack_tile(newtilebuf,unpackbuf,tile);
1365 clear_to_color(preview_bmp, 0);
1366
1367 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1368 puttile16(preview_bmp,tile,0,0,cs,flip);
1369 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1370
1371 clear_to_color(preview_bmp, 0);
1372 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1373 overtile16(preview_bmp,tile,0,0,cs,flip);
1374 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1375
1376 if(reftile > 0)
1377 {
1378 clear_to_color(preview_bmp, 0);
1379 jwin_draw_win(screen2, ref_til.x-2,ref_til.y-2, ref_til.w+4, ref_til.h+4, FR_DEEP);
1380 overtile16(preview_bmp,reftile,0,0,cs,flip);
1381 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, ref_til.x, ref_til.y, ref_til.w, ref_til.h);
1382 }
1383
1384 //Color info
1385 {
1386 color_info.h = 1;
1387 if(showcolortip)
1388 {
1389 auto fh = color_info.yscale = text_height(font);
1390 int ty = color_info.y;
1391 if(reftile <= 0)
1392 ty -= ref_til.h + 8;
1393 int y = ty;
1394 int rx = color_info.x+color_info.xscale;
1395 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1396 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1397 auto str = get_tile_colornames(tile,cs);
1398 size_t pos = 0;
1399 char buf[512] = {0};
1400 char cbuf[16] = {0};
1401 while(pos < str.size())
1402 {
1403 y += fh;
1404 if(y+fh > zq_screen_h)
1405 break; //Out of space!
1406 auto endpos = str.find_first_of('\n',pos);
1407
1408 if(endpos == std::string::npos)
1409 {
1410 strcpy(buf,str.substr(pos).c_str());
1411 pos = str.size();
1412 }
1413 else
1414 {
1415 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1416 pos = endpos+1;
1417 }
1418 //Ensure the name fits horizontally
1419 if(text_length(font,buf) > color_info.xscale)
1420 {
1421 size_t pos = 0;
1422 for(; buf[pos]; ++pos)
1423 {
1424 if(buf[pos] == ':')
1425 {
1426 strcpy(cbuf, buf+pos);
1427 buf[pos] = 0;
1428 break;
1429 }
1430 }
1431 size_t clen = text_length(font,cbuf);
1432 size_t dotlen = text_length(font,"..");
1433
1434 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1435 buf[--pos] = 0;
1436 while(buf[pos] == ' ')
1437 buf[pos] = 0;
1438 strcat(buf,"..");
1439 strcat(buf,cbuf);
1440 }
1441 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1442 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1443 ++color_info.h;
1444 }
1445 jwin_draw_frame(screen2,color_info.x-2,ty-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1446 }
1447 else
1448 {
1449 int ty = color_info_btn.y;
1450 if(reftile <= 0)
1451 ty -= ref_til.h + 8;
1452 draw_text_button(screen2,color_info_btn.x,ty,color_info_btn.w,color_info_btn.h,
1453 "Show Colors",vc(1),vc(14),0,true);
1454 }
1455 }
1456
1457 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1458
1459 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1460 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1461
1462 if(floating_sel)
1463 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1464 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1465 if(newtilebuf[tile].format==tf8Bit)
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1467 else
1468 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1469
1470 PALETTE temppal;
1471
1472 //palette and mouse
1473 switch(newtilebuf[tile].format)
1474 {
1475 case tf4Bit:
1476 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1477 get_palette(temppal);
1478
1479 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1480 {
1481 size_and_pos const& s = cpalette_4.subsquare(i);
1482 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1483 }
1484
1485 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1486 break;
1487
1488 case tf8Bit:
1489 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1490
1491 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1492 {
1493 size_and_pos const& s = cpalette_8.subsquare(i);
1494 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1495 }
1496
1497 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1498 break;
1499 }
1500
1501 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1502 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1503 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1504
1505 if(c2==0)
1506 {
1507 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1508 }
1509
1510 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1511 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1512 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1513
1514 if(c1==0)
1515 {
1516 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1517 }
1518
1519 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1520 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1521 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1522 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1523 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1524
1525 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1526 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527
1528 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1529 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1530
1531 bool qgrd = show_quartgrid && qgrid_tool(tool);
1532 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1533 for(int q = 0; q < REFL_MAX; ++q)
1534 {
1535 auto& sqr = reflbtn_grid.subsquare(q);
1536 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1537 }
1538 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1539 for(int q = 0; q < XMODE_MAX; ++q)
1540 {
1541 auto& sqr = xmodebtn_grid.subsquare(q);
1542 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1543 }
1544 for(int q = 0; q < BGMODE_MAX; ++q)
1545 {
1546 auto& sqr = bgmodebtn_grid.subsquare(q);
1547 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1548 }
1549
1550 //tool buttons
1551 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1552 {
1553 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1554 int col = toolbtn%tool_btns.w;
1555 int row = toolbtn/tool_btns.w;
1556
1557 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1558 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1559 }
1560
1561 //coordinates
1562 {
1563 auto mx = gui_mouse_x();
1564 auto my = gui_mouse_y();
1565 int32_t ind = zoomtile.rectind(mx,my);
1566 int32_t temp_x=ind%zoomtile.w;
1567 int32_t temp_y=ind/zoomtile.w;
1568 int color = -1;
1569
1570 bool is8b = newtilebuf[tile].format > tf4Bit;
1571 if(ind > -1)
1572 {
1573 char xbuf[16];
1574 sprintf(xbuf, "x: %d", temp_x);
1575 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1576 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1577 unpack_tile(newtilebuf, tile, 0, false);
1578 byte *si = unpackbuf;
1579 si+=ind;
1580 color = *si;
1581 }
1582 else if(fg_prev.rect(mx,my))
1583 color = c1;
1584 else if(bg_prev.rect(mx,my))
1585 color = c2;
1586 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1587 if(color > -1)
1588 {
1589 get_palette(tpal);
1590 char separator = ' ';
1591 char buf[512] = {0};
1592
1593 int realcol = color+(is8b?0:CSET(cs));
1594 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1595 auto& c = tpal[realcol];
1596
1597 if(tthighlight)
1598 {
1599 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1600 size_and_pos const& csqr = mainsqr.subsquare(color);
1601
1602 int hlcol = getHighlightColor(tpal[realcol]);
1603 int hlthick = 4;
1604 int extraborder = is8b ? 8 : 0;
1605 int borderthick = hlthick+extraborder;
1606
1607 if(is8b)
1608 {
1609 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1610 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1611 }
1612 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1613 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1614 if(xcolor)
1615 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1616 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1617 }
1618
1619 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1620 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1621
1622 strcpy(buf, get_color_name(realcol, is8b).c_str());
1623 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1624
1625 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1626 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1627
1628 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1629 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1630 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1631 if(xcolor)
1632 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1633 }
1634 }
1635
1636 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1637 update_tool_cursor();
1638 }
1639
1640 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1641 {
1642 unfloat_selection();
1643 if(tile>tile2)
1644 {
1645 zc_swap(tile, tile2);
1646 }
1647
1648 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1649 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1650
1651 int32_t start=tile;
1652 int32_t end=tile2;
1653
1654 // Might have top-right and bottom-left corners selected...
1655 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1656 {
1657 start=tile-(TILECOL(tile)-TILECOL(tile2));
1658 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1659 }
1660
1661 for(int32_t temptile=start; temptile<=end; temptile++)
1662 {
1663 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1664 {
1665 unpack_tile(newtilebuf, temptile, 0, true);
1666
1667 if(flip&1)
1668 {
1669 for(int32_t y=0; y<16; y++)
1670 {
1671 for(int32_t x=0; x<8; x++)
1672 {
1673 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1674 }
1675 }
1676 }
1677
1678 if(flip&2)
1679 {
1680 for(int32_t y=0; y<8; y++)
1681 {
1682 for(int32_t x=0; x<16; x++)
1683 {
1684 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1685 }
1686 }
1687 }
1688
1689 pack_tile(newtilebuf,unpackbuf,temptile);
1690 }
1691 }
1692 }
1693
1694 void rotate_tile(int32_t tile, bool backward)
1695 {
1696 unfloat_selection();
1697 unpack_tile(newtilebuf, tile, 0, true);
1698 byte tempunpackbuf[256];
1699 byte tempx, tempy;
1700
1701 for(tempx=0; tempx<16; tempx++)
1702 {
1703 for(tempy=0; tempy<16; tempy++)
1704 {
1705 if(!backward)
1706 {
1707 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1708 }
1709 else
1710 {
1711 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1712 }
1713 }
1714 }
1715
1716 pack_tile(newtilebuf,tempunpackbuf,tile);
1717 }
1718
1719 static int32_t undocount=128;
1720 byte undotile[256];
1721
1722 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1723 {
1724 byte buf[256];
1725
1726 for(int32_t i=0; i<undocount; i++)
1727 {
1728 newtilebuf[tile].data[i]=undotile[i];
1729 }
1730
1731 if(!(horizontal||vertical))
1732 {
1733 return;
1734 }
1735
1736 unpack_tile(newtilebuf, tile, 0, true);
1737
1738 for(int32_t i=0; i<256; i++)
1739 {
1740 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1741 buf[shift_ind] = unpackbuf[i];
1742 }
1743
1744 if(clear)
1745 {
1746 for(int32_t r=0; r<abs(vertical); r++)
1747 {
1748 for(int32_t c=0; c<16; c++)
1749 {
1750 buf[(vertical>0?r:15-r)*16+c]=0;
1751 }
1752 }
1753
1754 for(int32_t r=0; r<16; r++)
1755 {
1756 for(int32_t c=0; c<abs(horizontal); c++)
1757 {
1758 buf[r*16+(horizontal>0?c:15-c)]=0;
1759 }
1760 }
1761 }
1762
1763 pack_tile(newtilebuf,buf,tile);
1764 }
1765
1766 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1767 {
1768 byte buf[256];
1769
1770 if(!(horizontal||vertical))
1771 {
1772 return;
1773 }
1774
1775 memset(buf,0,256);
1776
1777 for(int32_t i=0; i<256; i++)
1778 {
1779 if(is_in_selection(i%16,i/16))
1780 {
1781 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1782 buf[shift_ind] = floatsel[i];
1783 }
1784 }
1785
1786 memcpy(floatsel,buf,256);
1787 }
1788
1789 void float_selection(int32_t tile, bool clear)
1790 {
1791 if(floating_sel) return;
1792 floating_sel = true;
1793 floating_tile = tile;
1794
1795 unpack_tile(newtilebuf, tile, 0, true);
1796
1797 for(auto q = 0; q < 256; ++q)
1798 {
1799 if(is_in_selection(q%16,q/16))
1800 {
1801 floatsel[q] = unpackbuf[q];
1802 unpackbuf[q] = clear ? 0 : c2;
1803 }
1804 else floatsel[q] = 0;
1805 }
1806
1807 pack_tile(newtilebuf,unpackbuf,tile);
1808 }
1809
1810 void unfloat_selection()
1811 {
1812 if(!floating_sel) return;
1813 floating_sel = false;
1814
1815 unpack_tile(newtilebuf, floating_tile, 0, true);
1816
1817 for(auto q = 0; q < 256; ++q)
1818 {
1819 if(floatsel[q])
1820 {
1821 unpackbuf[q] = floatsel[q];
1822 }
1823 }
1824
1825 pack_tile(newtilebuf,unpackbuf,floating_tile);
1826 floating_tile = -1;
1827 }
1828
1829 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1830 {
1831 if(floating_sel)
1832 {
1833 for(auto q = 0; q < 256; ++q)
1834 {
1835 if(ignore_transparent && floatsel[q]==0)
1836 continue;
1837 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1838 }
1839 return;
1840 }
1841
1842 byte buf[256];
1843 unpack_tile(newtilebuf, tile, 0, true);
1844
1845 for(int32_t i=0; i<256; i++)
1846 {
1847 buf[i]=unpackbuf[i];
1848
1849 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1850 continue;
1851
1852 if(ignore_transparent)
1853 {
1854 if(buf[i]==0)
1855 continue;
1856
1857 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1858 }
1859 else // Don't ignore transparent
1860 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1861 }
1862
1863 pack_tile(newtilebuf,buf,tile);
1864 }
1865
1866 void clear_selection_grid()
1867 {
1868 unfloat_selection();
1869 for(int32_t x=0; x<18; ++x)
1870 {
1871 for(int32_t y=0; y<18; ++y)
1872 {
1873 selection_grid[x][y]=0;
1874 }
1875 }
1876 }
1877
1878 void invert_selection_grid()
1879 {
1880 unfloat_selection();
1881 for(int32_t x=1; x<17; ++x)
1882 {
1883 for(int32_t y=1; y<17; ++y)
1884 {
1885 selection_grid[x][y]=selection_grid[x][y]?0:1;
1886 }
1887 }
1888 }
1889
1890 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1891 {
1892 byte local_grid[16][16];
1893 memset(local_grid, 0, sizeof(local_grid));
1894 for(auto x = 0; x < 16; ++x)
1895 {
1896 for(auto y = 0; y < 16; ++y)
1897 {
1898 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1899 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1900 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1901 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1902 }
1903 }
1904 for(auto x = 0; x < 16; ++x)
1905 {
1906 for(auto y = 0; y < 16; ++y)
1907 {
1908 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1909 }
1910 }
1911 }
1912
1913 void show_edit_tile_help()
1914 {
1915 InfoDialog("Help: Tile Editor", "Hotkeys:"
1916 "\nF1: This Help Dialog"
1917 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1918 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1919 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1920 "\nH/V: Flip | (Shift+)R: Rotate"
1921 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1922 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1923 "\nF12: Screenshot (whole screen)"
1924 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1925 "\nWhen not on Select tools, hold to swap:"
1926 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1927 }
1928
1929 static int move_origin_x=-1, move_origin_y=-1;
1930 static int prev_x=-1, prev_y=-1;
1931 bool __pixel_draw(int x, int y, int tile, int flip)
1932 {
1933 bool ret = false;
1934 switch(tool)
1935 {
1936 case t_pen:
1937 if(flip&1) x=15-x;
1938
1939 if(flip&2) y=15-y;
1940
1941 if(is_in_selection(x,y))
1942 {
1943 if(floating_sel)
1944 {
1945 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1946 }
1947 else
1948 {
1949 unpack_tile(newtilebuf, tile, 0, false);
1950 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1951 pack_tile(newtilebuf, unpackbuf,tile);
1952 }
1953 }
1954 break;
1955
1956 case t_fill:
1957 if(is_in_selection(x,y))
1958 {
1959 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1960 ret = true;
1961 }
1962 break;
1963
1964 case t_recolor:
1965 if(is_in_selection(x,y))
1966 {
1967 if(floating_sel)
1968 {
1969 tf_u = floatsel[(y<<4)+x];
1970 for(int32_t i=0; i<256; i++)
1971 {
1972 if(is_in_selection(i&15,i>>4))
1973 {
1974 if(floatsel[i]==tf_u)
1975 {
1976 floatsel[i]=(drawing==1)?c1:c2;
1977 }
1978 }
1979 }
1980 }
1981 else
1982 {
1983 unpack_tile(newtilebuf, tile, 0, false);
1984 tf_u = unpackbuf[(y<<4)+x];
1985 if(tf_u != ((drawing==1)?c1:c2))
1986 {
1987 for(int32_t i=0; i<256; i++)
1988 {
1989 if(is_in_selection(i&15,i>>4))
1990 {
1991 if(unpackbuf[i]==tf_u)
1992 {
1993 unpackbuf[i]=(drawing==1)?c1:c2;
1994 }
1995 }
1996 }
1997
1998 pack_tile(newtilebuf, unpackbuf,tile);
1999 }
2000 }
2001 ret = true;
2002 }
2003 break;
2004
2005 case t_eyedropper:
2006 if(floating_sel)
2007 memcpy(unpackbuf, floatsel, 256);
2008 else unpack_tile(newtilebuf, tile, 0, false);
2009
2010 if(gui_mouse_b()&1)
2011 {
2012 c1=unpackbuf[((y<<4)+x)];
2013 }
2014
2015 if(gui_mouse_b()&2)
2016 {
2017 c2=unpackbuf[((y<<4)+x)];
2018 }
2019 break;
2020
2021 case t_move:
2022 if((prev_x!=x)||(prev_y!=y))
2023 {
2024 if(has_selection())
2025 {
2026 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2027 wrap_sel_tile(y-prev_y, x-prev_x);
2028 shift_selection_grid(x-prev_x, y-prev_y);
2029 }
2030 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2031 prev_x=x;
2032 prev_y=y;
2033 }
2034 break;
2035
2036 case t_select:
2037 unfloat_selection();
2038 if(flip&1) x=15-x;
2039
2040 if(flip&2) y=15-y;
2041
2042 if(selecting_x1==-1||selecting_y1==-1)
2043 {
2044 selecting_x1=x;
2045 selecting_y1=y;
2046 }
2047 else
2048 {
2049 selecting_x2=x;
2050 selecting_y2=y;
2051 }
2052 break;
2053
2054 case t_wand:
2055 unfloat_selection();
2056 if(flip&1) x=15-x;
2057
2058 if(flip&2) y=15-y;
2059
2060 switch(select_mode)
2061 {
2062 case 0:
2063 clear_selection_grid();
2064 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2065 break;
2066
2067 case 1:
2068 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2069 break;
2070
2071 case 2:
2072 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2073 break;
2074
2075 case 3:
2076 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2077 break;
2078 }
2079
2080 ret = true;
2081 break;
2082 }
2083 return ret;
2084 }
2085 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2086 {
2087 popup_zqdialog_start();
2088 FONT* oldfont = font;
2089 font = get_custom_font(CFONT_DLG);
2090 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2091 status_info.yscale = text_height(font);
2092 status_info.y = 308-(status_info.h*status_info.yscale);
2093 hover_info.yscale = status_info.yscale;
2094 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2095 undocount = tilesize(newtilebuf[tile].format);
2096 clear_selection_grid();
2097 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2098
2099 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2100 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2101
2102 PALETTE tpal;
2103 byte oldtile[256];
2104
2105 memset(&tpal, 0, sizeof(PALETTE));
2106 memset(oldtile, 0, 256);
2107
2108 for(int32_t i=0; i<undocount; i++)
2109 {
2110 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2111 }
2112 byte undoselgrid[16][16];
2113 for(auto x = 0; x < 16; ++x)
2114 for(auto y = 0; y < 16; ++y)
2115 undoselgrid[x][y] = selection_grid[x+1][y+1];
2116 for(auto q = 0; q < 256; ++q)
2117 {
2118 floatsel[q] = 0;
2119 undofloatsel[q] = 0;
2120 floating_sel = false;
2121 undo_is_floatsel = false;
2122 }
2123
2124 int32_t tile_x=-1, tile_y=-1;
2125 int32_t temp_x=-1, temp_y=-1;
2126 bool bdown=false;
2127 int32_t done=0;
2128 drawing=0;
2129 tool_cur = -1;
2130
2131 get_palette(tpal);
2132
2133 if(newtilebuf[tile].format==tf4Bit)
2134 {
2135 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2136 }
2137 else
2138 {
2139 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2140 }
2141
2142 zc_set_palette(tpal);
2143 draw_edit_scr(tile,flip,cs,oldtile, true);
2144 anim_hw_screen();
2145 while(gui_mouse_b()) rest(1);
2146
2147 move_origin_x=-1;
2148 move_origin_y=-1;
2149 prev_x=-1;
2150 prev_y=-1;
2151
2152
2153
2154 byte selection_pattern_source[8][8]=
2155 {
2156 {1, 1, 1, 1, 0, 0, 0, 0},
2157 {1, 1, 1, 0, 0, 0, 0, 1},
2158 {1, 1, 0, 0, 0, 0, 1, 1},
2159 {1, 0, 0, 0, 0, 1, 1, 1},
2160 {0, 0, 0, 0, 1, 1, 1, 1},
2161 {0, 0, 0, 1, 1, 1, 1, 0},
2162 {0, 0, 1, 1, 1, 1, 0, 0},
2163 {0, 1, 1, 1, 1, 0, 0, 0},
2164 };
2165
2166 byte selecting_pattern_source[8][8]=
2167 {
2168 {1, 1, 0, 0, 0, 0, 1, 1},
2169 {1, 0, 0, 0, 0, 1, 1, 1},
2170 {0, 0, 0, 0, 1, 1, 1, 1},
2171 {0, 0, 0, 1, 1, 1, 1, 0},
2172 {0, 0, 1, 1, 1, 1, 0, 0},
2173 {0, 1, 1, 1, 1, 0, 0, 0},
2174 {1, 1, 1, 1, 0, 0, 0, 0},
2175 {1, 1, 1, 0, 0, 0, 0, 1},
2176 };
2177
2178 byte intersection_pattern_source[8][8]=
2179 {
2180 {0, 0, 1, 1, 0, 0, 1, 1},
2181 {0, 1, 1, 0, 0, 1, 1, 0},
2182 {1, 1, 0, 0, 1, 1, 0, 0},
2183 {1, 0, 0, 1, 1, 0, 0, 1},
2184 {0, 0, 1, 1, 0, 0, 1, 1},
2185 {0, 1, 1, 0, 0, 1, 1, 0},
2186 {1, 1, 0, 0, 1, 1, 0, 0},
2187 {1, 0, 0, 1, 1, 0, 0, 1},
2188 };
2189
2190 selection_pattern=create_bitmap_ex(8, 8, 8);
2191
2192 for(int32_t x=0; x<8; ++x)
2193 {
2194 for(int32_t y=0; y<8; ++y)
2195 {
2196 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2197 }
2198 }
2199
2200 selecting_pattern=create_bitmap_ex(8, 8, 8);
2201
2202 for(int32_t x=0; x<8; ++x)
2203 {
2204 for(int32_t y=0; y<8; ++y)
2205 {
2206 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2207 }
2208 }
2209
2210 intersection_pattern=create_bitmap_ex(8, 8, 8);
2211
2212 for(int32_t x=0; x<8; ++x)
2213 {
2214 for(int32_t y=0; y<8; ++y)
2215 {
2216 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2217 }
2218 }
2219
2220 do
2221 {
2222 HANDLE_CLOSE_ZQDLG();
2223 if(exiting_program) break;
2224 int32_t temp_mouse_x=gui_mouse_x();
2225 int32_t temp_mouse_y=gui_mouse_y();
2226 //rest(4);
2227 bool redraw=false;
2228 bool did_wand_select=false;
2229
2230 if(keypressed())
2231 {
2232 bool ctrl = CHECK_CTRL_CMD;
2233 int k = readkey()>>8;
2234 switch(k)
2235 {
2236 case KEY_F1:
2237 show_edit_tile_help();
2238 break;
2239 case KEY_ENTER_PAD:
2240 case KEY_ENTER:
2241 if(floating_sel)
2242 unfloat_selection();
2243 else done=2;
2244 break;
2245
2246 case KEY_ESC:
2247 if(floating_sel)
2248 unfloat_selection();
2249 else if(has_selection())
2250 clear_selection_grid();
2251 else done=1;
2252 break;
2253
2254 case KEY_DEL:
2255 {
2256 unpack_tile(newtilebuf, tile, 0, false);
2257 bool all = CHECK_CTRL_CMD || !has_selection();
2258 bool canDel = false;
2259 if(all)
2260 {
2261 //Check all
2262 for(auto q = 0; q < 256; ++q)
2263 if(unpackbuf[q])
2264 {
2265 canDel = true;
2266 break;
2267 }
2268 }
2269 else
2270 {
2271 //Check selection
2272 for(auto x = 0; x < 16; ++x)
2273 for(auto y = 0; y < 16; ++y)
2274 if(is_in_selection(x,y))
2275 if(unpackbuf[(y<<4)+x])
2276 {
2277 canDel = true;
2278 break;
2279 }
2280 }
2281 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2282
2283 for(int32_t i=0; i<undocount; i++)
2284 {
2285 undotile[i]=newtilebuf[tile].data[i];
2286 }
2287 for(auto x = 0; x < 16; ++x)
2288 for(auto y = 0; y < 16; ++y)
2289 undoselgrid[x][y] = selection_grid[x+1][y+1];
2290 for(auto q = 0; q < 256; ++q)
2291 undofloatsel[q] = floatsel[q];
2292 undo_is_floatsel = floating_sel;
2293
2294 if(CHECK_CTRL_CMD || !has_selection())
2295 {
2296 //Delete all
2297 for(auto q = 0; q < 256; ++q)
2298 {
2299 unpackbuf[q] = 0;
2300 floatsel[q] = 0;
2301 }
2302 }
2303 else
2304 {
2305 //Delete selection
2306 for(auto x = 0; x < 16; ++x)
2307 for(auto y = 0; y < 16; ++y)
2308 {
2309 if(floating_sel)
2310 {
2311 floatsel[x+(y<<4)] = 0;
2312 }
2313 else if(is_in_selection(x,y))
2314 {
2315 unpackbuf[(y<<4)+x] = 0;
2316 }
2317 }
2318 }
2319 pack_tile(newtilebuf, unpackbuf, tile);
2320 redraw=true;
2321 }
2322 break;
2323
2324 case KEY_A:
2325 clear_selection_grid();
2326 invert_selection_grid();
2327 redraw=true;
2328 break;
2329
2330 case KEY_D:
2331 clear_selection_grid();
2332 redraw=true;
2333 break;
2334
2335 case KEY_I:
2336 invert_selection_grid();
2337 redraw=true;
2338 break;
2339
2340 case KEY_H:
2341 flip^=1;
2342 normalize(tile,tile,0,flip);
2343 flip=0;
2344 redraw=true;
2345 break;
2346
2347 case KEY_V:
2348 flip^=2;
2349 normalize(tile,tile,0,flip);
2350 flip=0;
2351 redraw=true;
2352 break;
2353
2354 case KEY_F12:
2355 onSnapshot();
2356 break;
2357
2358 case KEY_R:
2359 {
2360 //if(CHECK_CTRL_CMD))
2361 // {
2362 //do_recolor(tile); redraw=true; mark_save_dirty();
2363 // }
2364 //else
2365 // {
2366 go_tiles();
2367 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2368 redraw=true;
2369 mark_save_dirty();
2370 break;
2371 }
2372
2373 case KEY_EQUALS:
2374 case KEY_PLUS_PAD:
2375 {
2376 if(CHECK_CTRL_CMD ||
2377 key[KEY_ALT] || key[KEY_ALTGR])
2378 {
2379 for(int32_t i=0; i<undocount; i++)
2380 undotile[i]=newtilebuf[tile].data[i];
2381 for(auto x = 0; x < 16; ++x)
2382 for(auto y = 0; y < 16; ++y)
2383 undoselgrid[x][y] = selection_grid[x+1][y+1];
2384 for(auto q = 0; q < 256; ++q)
2385 undofloatsel[q] = floatsel[q];
2386 undo_is_floatsel = floating_sel;
2387
2388 if(key[KEY_ALT] || key[KEY_ALTGR])
2389 shift_tile_colors(tile, 16, false);
2390 else
2391 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2392 }
2393 else
2394 cs = (cs<13) ? cs+1:0;
2395
2396 redraw=true;
2397 break;
2398 }
2399
2400 case KEY_MINUS:
2401 case KEY_MINUS_PAD:
2402 {
2403 if(CHECK_CTRL_CMD ||
2404 key[KEY_ALT] || key[KEY_ALTGR])
2405 {
2406 for(int32_t i=0; i<undocount; i++)
2407 undotile[i]=newtilebuf[tile].data[i];
2408 for(auto x = 0; x < 16; ++x)
2409 for(auto y = 0; y < 16; ++y)
2410 undoselgrid[x][y] = selection_grid[x+1][y+1];
2411 for(auto q = 0; q < 256; ++q)
2412 undofloatsel[q] = floatsel[q];
2413 undo_is_floatsel = floating_sel;
2414
2415 if(key[KEY_ALT] || key[KEY_ALTGR])
2416 shift_tile_colors(tile, -16, false);
2417 else
2418 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2419 }
2420 else
2421 cs = (cs>0) ? cs-1:13;
2422
2423 redraw=true;
2424 break;
2425 }
2426
2427 case KEY_SPACE:
2428 gridmode=(gridmode+1)%gm_max;
2429 redraw=true;
2430 break;
2431
2432 case KEY_Z:
2433 if(!ctrl)
2434 break;
2435 //Ctrl+Z == undo
2436 [[fallthrough]];
2437 case KEY_U:
2438 for(int32_t i=0; i<undocount; i++)
2439 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2440
2441 for(auto x = 0; x < 16; ++x)
2442 for(auto y = 0; y < 16; ++y)
2443 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2444
2445 for(auto q = 0; q < 256; ++q)
2446 zc_swap(undofloatsel[q], floatsel[q]);
2447 zc_swap(undo_is_floatsel, floating_sel);
2448
2449 redraw=true;
2450 break;
2451
2452 case KEY_S:
2453 if(CHECK_CTRL_CMD)
2454 {
2455 for(int32_t i=0; i<undocount; i++)
2456 {
2457 undotile[i]=newtilebuf[tile].data[i];
2458 }
2459 for(auto x = 0; x < 16; ++x)
2460 for(auto y = 0; y < 16; ++y)
2461 undoselgrid[x][y] = selection_grid[x+1][y+1];
2462 for(auto q = 0; q < 256; ++q)
2463 undofloatsel[q] = floatsel[q];
2464 undo_is_floatsel = floating_sel;
2465
2466 unpack_tile(newtilebuf, tile, 0, false);
2467
2468 if(has_selection())
2469 {
2470 for(int32_t i=0; i<256; i++)
2471 {
2472 if(!is_in_selection(i%16,i/16))
2473 continue;
2474 if(unpackbuf[i]==c1)
2475 {
2476 unpackbuf[i]=c2;
2477 }
2478 else if(unpackbuf[i]==c2)
2479 {
2480 unpackbuf[i]=c1;
2481 }
2482 if(floating_sel)
2483 {
2484 if(floatsel[i]==c1)
2485 {
2486 floatsel[i]=c2;
2487 }
2488 else if(floatsel[i]==c2)
2489 {
2490 floatsel[i]=c1;
2491 }
2492 }
2493 }
2494 }
2495 else
2496 {
2497 for(int32_t i=0; i<256; i++)
2498 {
2499 if(unpackbuf[i]==c1)
2500 {
2501 unpackbuf[i]=c2;
2502 }
2503 else if(unpackbuf[i]==c2)
2504 {
2505 unpackbuf[i]=c1;
2506 }
2507 }
2508 }
2509
2510 pack_tile(newtilebuf, unpackbuf,tile);
2511 }
2512
2513 zc_swap(c1,c2);
2514 redraw=true;
2515 break;
2516
2517 case KEY_UP:
2518 if(CHECK_CTRL_CMD)
2519 {
2520 unfloat_selection();
2521 tile=zc_max(0,tile-TILES_PER_ROW);
2522 undocount = tilesize(newtilebuf[tile].format);
2523
2524 for(int32_t i=0; i<undocount; i++)
2525 {
2526 undotile[i]=newtilebuf[tile].data[i];
2527 oldtile[i]=undotile[i];
2528 }
2529
2530 redraw=true;
2531 }
2532 else
2533 {
2534 for(int32_t i=0; i<undocount; i++)
2535 {
2536 undotile[i]=newtilebuf[tile].data[i];
2537 }
2538 for(auto x = 0; x < 16; ++x)
2539 for(auto y = 0; y < 16; ++y)
2540 undoselgrid[x][y] = selection_grid[x+1][y+1];
2541 for(auto q = 0; q < 256; ++q)
2542 undofloatsel[q] = floatsel[q];
2543 undo_is_floatsel = floating_sel;
2544 if(has_selection())
2545 {
2546 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2547 wrap_sel_tile(-1, 0);
2548 shift_selection_grid(0, -1);
2549 }
2550 else wrap_tile(tile, -1, 0, false);
2551 redraw=true;
2552 }
2553 break;
2554
2555 case KEY_DOWN:
2556 if(CHECK_CTRL_CMD)
2557 {
2558 unfloat_selection();
2559 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2560 undocount = tilesize(newtilebuf[tile].format);
2561
2562 for(int32_t i=0; i<undocount; i++)
2563 {
2564 undotile[i]=newtilebuf[tile].data[i];
2565 oldtile[i]=undotile[i];
2566 }
2567
2568 redraw=true;
2569 }
2570 else
2571 {
2572 for(int32_t i=0; i<undocount; i++)
2573 {
2574 undotile[i]=newtilebuf[tile].data[i];
2575 }
2576 for(auto x = 0; x < 16; ++x)
2577 for(auto y = 0; y < 16; ++y)
2578 undoselgrid[x][y] = selection_grid[x+1][y+1];
2579 for(auto q = 0; q < 256; ++q)
2580 undofloatsel[q] = floatsel[q];
2581 undo_is_floatsel = floating_sel;
2582 if(has_selection())
2583 {
2584 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2585 wrap_sel_tile(1, 0);
2586 shift_selection_grid(0, 1);
2587 }
2588 else wrap_tile(tile, 1, 0, false);
2589 redraw=true;
2590 }
2591 break;
2592
2593 case KEY_LEFT:
2594 if(CHECK_CTRL_CMD)
2595 {
2596 unfloat_selection();
2597 tile=zc_max(0,tile-1);
2598 undocount = tilesize(newtilebuf[tile].format);
2599
2600 for(int32_t i=0; i<undocount; i++)
2601 {
2602 undotile[i]=newtilebuf[tile].data[i];
2603 oldtile[i]=undotile[i];
2604 }
2605
2606 redraw=true;
2607 }
2608 else
2609 {
2610 for(int32_t i=0; i<undocount; i++)
2611 {
2612 undotile[i]=newtilebuf[tile].data[i];
2613 }
2614 for(auto x = 0; x < 16; ++x)
2615 for(auto y = 0; y < 16; ++y)
2616 undoselgrid[x][y] = selection_grid[x+1][y+1];
2617 for(auto q = 0; q < 256; ++q)
2618 undofloatsel[q] = floatsel[q];
2619 undo_is_floatsel = floating_sel;
2620 if(has_selection())
2621 {
2622 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2623 wrap_sel_tile(0, -1);
2624 shift_selection_grid(-1, 0);
2625 }
2626 else wrap_tile(tile, 0, -1, false);
2627 redraw=true;
2628 }
2629 break;
2630
2631 case KEY_RIGHT:
2632 if(CHECK_CTRL_CMD)
2633 {
2634 unfloat_selection();
2635 tile=zc_min(tile+1, NEWMAXTILES-1);
2636 undocount = tilesize(newtilebuf[tile].format);
2637
2638 for(int32_t i=0; i<undocount; i++)
2639 {
2640 undotile[i]=newtilebuf[tile].data[i];
2641 oldtile[i]=undotile[i];
2642 }
2643
2644 redraw=true;
2645 }
2646 else
2647 {
2648 for(int32_t i=0; i<undocount; i++)
2649 {
2650 undotile[i]=newtilebuf[tile].data[i];
2651 }
2652 for(auto x = 0; x < 16; ++x)
2653 for(auto y = 0; y < 16; ++y)
2654 undoselgrid[x][y] = selection_grid[x+1][y+1];
2655 for(auto q = 0; q < 256; ++q)
2656 undofloatsel[q] = floatsel[q];
2657 undo_is_floatsel = floating_sel;
2658 if(has_selection())
2659 {
2660 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2661 wrap_sel_tile(0, 1);
2662 shift_selection_grid(1, 0);
2663 }
2664 else wrap_tile(tile, 0, 1, false);
2665 redraw=true;
2666 }
2667 break;
2668 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2669 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2670 case KEY_8: case KEY_9:
2671 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2672 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2673 case KEY_8_PAD: case KEY_9_PAD:
2674 {
2675 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2676 if(unsigned(t) < t_max)
2677 {
2678 if(old_tool != -1)
2679 old_tool = t;
2680 else tool = t;
2681 }
2682 break;
2683 }
2684 case KEY_TAB:
2685 {
2686 if(key_shifts & KB_CTRL_CMD_FLAG)
2687 {
2688 xmode = (xmode+1)%XMODE_MAX;
2689 if(!xmode)
2690 bgmode = (bgmode+1)%BGMODE_MAX;
2691 }
2692 else if(key_shifts & KB_SHIFT_FLAG)
2693 hide_grid = !hide_grid;
2694 else show_quartgrid = !show_quartgrid;
2695 redraw = true;
2696 break;
2697 }
2698 }
2699 clear_keybuf();
2700 }
2701
2702 if(!gui_mouse_b())
2703 {
2704 if(is_selecting())
2705 {
2706 unfloat_selection();
2707 int32_t x1=zc_min(selecting_x1,selecting_x2);
2708 int32_t x2=zc_max(selecting_x1,selecting_x2);
2709 int32_t y1=zc_min(selecting_y1,selecting_y2);
2710 int32_t y2=zc_max(selecting_y1,selecting_y2);
2711
2712 if(select_mode==0)
2713 {
2714 clear_selection_grid();
2715 }
2716
2717 for(int32_t x=x1; x<=x2; ++x)
2718 {
2719 for(int32_t y=y1; y<=y2; ++y)
2720 {
2721 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2722 }
2723 }
2724
2725 if(select_mode==3)
2726 {
2727 for(int32_t y=0; y<16; ++y)
2728 {
2729 for(int32_t x=0; x<x1; ++x)
2730 {
2731 selection_grid[x+1][y+1]=0;
2732 }
2733
2734 for(int32_t x=x2+1; x<16; ++x)
2735 {
2736 selection_grid[x+1][y+1]=0;
2737 }
2738 }
2739
2740 for(int32_t x=x1; x<=x2; ++x)
2741 {
2742 for(int32_t y=0; y<y1; ++y)
2743 {
2744 selection_grid[x+1][y+1]=0;
2745 }
2746
2747 for(int32_t y=y2+1; y<16; ++y)
2748 {
2749 selection_grid[x+1][y+1]=0;
2750 }
2751 }
2752 }
2753 }
2754
2755 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2756 did_wand_select=false;
2757 }
2758
2759 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2760 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2761 bool ctrl=CHECK_CTRL_CMD;
2762 static int32_t last_tool_val = 0;
2763
2764 if(tool==t_select||tool==t_wand)
2765 {
2766 if(!drawing)
2767 {
2768 int32_t type=0;
2769
2770 if(has_selection())
2771 {
2772 if(shift)
2773 {
2774 type+=1;
2775 }
2776
2777 if(alt)
2778 {
2779 type+=2;
2780 }
2781 }
2782
2783 if(type!=select_mode)
2784 {
2785 select_mode=type;
2786
2787 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2788 set_tool_sprite(tool,type);
2789 }
2790 }
2791 }
2792 else if(alt||ctrl)
2793 {
2794 if(old_tool==-1)
2795 {
2796 old_tool = tool;
2797 tool_cur = -1;
2798 }
2799 if(alt&&ctrl)
2800 tool = t_recolor;
2801 else if(alt)
2802 tool = t_eyedropper;
2803 else tool = t_fill;
2804 }
2805 else if(old_tool!=-1)
2806 {
2807 tool = old_tool;
2808 old_tool = -1;
2809 tool_cur = -1;
2810 redraw = true;
2811 }
2812 if(last_tool_val != tool)
2813 {
2814 redraw = true;
2815 tool_cur = -1;
2816 update_tool_cursor();
2817 last_tool_val = tool;
2818 }
2819
2820 if(!bdown)
2821 {
2822 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2823 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2824 }
2825
2826 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2827 {
2828 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2829 {
2830 if(tool==t_move || tool==t_fill)
2831 {
2832 set_tool_sprite(tool,1);
2833
2834 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2835 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2836 }
2837
2838 for(int32_t i=0; i<undocount; i++)
2839 {
2840 undotile[i]=newtilebuf[tile].data[i];
2841 }
2842 for(auto x = 0; x < 16; ++x)
2843 for(auto y = 0; y < 16; ++y)
2844 undoselgrid[x][y] = selection_grid[x+1][y+1];
2845 for(auto q = 0; q < 256; ++q)
2846 undofloatsel[q] = floatsel[q];
2847 undo_is_floatsel = floating_sel;
2848
2849 drawing=1;
2850 }
2851
2852 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2853 {
2854 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2855 {
2856 done=2;
2857 }
2858 }
2859
2860 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2861 {
2862 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2863 {
2864 done=1;
2865 }
2866 }
2867
2868 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2869 {
2870 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2871 {
2872 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2873 get_palette(tpal);
2874
2875 if(newtilebuf[tile].format==tf4Bit)
2876 {
2877 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2878 }
2879 else
2880 {
2881 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2882 }
2883
2884 redraw=true;
2885 }
2886 }
2887
2888 int sqr_clicked;
2889 if(show_quartgrid && qgrid_tool(tool))
2890 {
2891 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2892 if(sqr_clicked > -1)
2893 {
2894 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2895 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2896 refl_flags ^= (1<<sqr_clicked);
2897 }
2898 }
2899 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2900 if(sqr_clicked > -1)
2901 {
2902 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2903 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2904 xmode = sqr_clicked;
2905 }
2906 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2907 if(sqr_clicked > -1)
2908 {
2909 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2910 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2911 bgmode = sqr_clicked;
2912 }
2913
2914 if(showcolortip)
2915 {
2916 auto oy = color_info.y;
2917 if(reftile <= 0)
2918 color_info.y -= ref_til.h + 8;
2919 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2920 {
2921 showcolortip = 0;
2922 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2923 }
2924 color_info.y = oy;
2925 }
2926 else
2927 {
2928 auto oy = color_info_btn.y;
2929 if(reftile <= 0)
2930 color_info_btn.y -= ref_til.h + 8;
2931 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2932 {
2933 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2934 {
2935 showcolortip = 1;
2936 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2937 redraw=true;
2938 }
2939 }
2940 color_info_btn.y = oy;
2941 }
2942
2943 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2944 {
2945 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2946 {
2947 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2948 redraw=true;
2949 }
2950 }
2951 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2952 {
2953 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2954 redraw=true;
2955 }
2956 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2957 {
2958 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2959 redraw=true;
2960 }
2961
2962 switch(newtilebuf[tile].format)
2963 {
2964 case tf4Bit:
2965 {
2966 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2967 if(ind > -1)
2968 {
2969 c1 = ind;
2970 redraw=true;
2971 }
2972 break;
2973 }
2974 case tf8Bit:
2975 {
2976 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2977 if(ind > -1)
2978 {
2979 c1 = ind;
2980 redraw=true;
2981 }
2982 break;
2983 }
2984 }
2985
2986
2987 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2988 if(newtool > -1 && newtool < t_max)
2989 {
2990 tool=newtool;
2991 redraw=true;
2992 }
2993
2994 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2995 {
2996 if(do_x_button(screen, x_btn.x, x_btn.y))
2997 {
2998 done=1;
2999 }
3000 }
3001 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3002 {
3003 if(do_question_button(screen, info_btn.x, info_btn.y))
3004 {
3005 show_edit_tile_help();
3006 }
3007 }
3008
3009 bdown=true;
3010 }
3011
3012 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3013 {
3014 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3015 {
3016 if(tool==t_move || tool==t_fill)
3017 {
3018 set_tool_sprite(tool,1);
3019
3020 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3021 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3022 }
3023
3024 for(int32_t i=0; i<undocount; i++)
3025 {
3026 undotile[i]=newtilebuf[tile].data[i];
3027 }
3028 for(auto x = 0; x < 16; ++x)
3029 for(auto y = 0; y < 16; ++y)
3030 undoselgrid[x][y] = selection_grid[x+1][y+1];
3031 for(auto q = 0; q < 256; ++q)
3032 undofloatsel[q] = floatsel[q];
3033 undo_is_floatsel = floating_sel;
3034
3035 drawing=2;
3036 }
3037
3038 switch(newtilebuf[tile].format)
3039 {
3040 case tf4Bit:
3041 {
3042 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3043 if(ind > -1)
3044 {
3045 c2 = ind;
3046 redraw=true;
3047 }
3048 break;
3049 }
3050 case tf8Bit:
3051 {
3052 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3053 if(ind > -1)
3054 {
3055 c2 = ind;
3056 redraw=true;
3057 }
3058 break;
3059 }
3060 }
3061
3062 bdown=true;
3063 }
3064
3065 if(bdown&&!gui_mouse_b()) //released the buttons
3066 {
3067 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3068 {
3069 if(tool==t_move || tool==t_fill)
3070 {
3071 set_tool_sprite(tool,0);
3072 }
3073 }
3074 }
3075
3076 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3077 {
3078 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3079 int32_t x=ind%zoomtile.w;
3080 int32_t y=ind/zoomtile.w;
3081
3082 bool reset_draw = false;
3083
3084 if(__pixel_draw(x,y,tile,flip))
3085 reset_draw = true;
3086 if(show_quartgrid)
3087 {
3088 auto tmp_sel_mode = select_mode;
3089 if(tool == t_wand && select_mode == 0)
3090 select_mode = 1;
3091 if(qgrid_tool(tool))
3092 {
3093 if(refl_flags & (1<<REFL_HFLIP))
3094 if(__pixel_draw(15-x,y,tile,flip))
3095 reset_draw = true;
3096 if(refl_flags & (1<<REFL_VFLIP))
3097 if(__pixel_draw(x,15-y,tile,flip))
3098 reset_draw = true;
3099 //Diagonal flip and 180° rotation are the same!
3100 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3101 if(__pixel_draw(15-x,15-y,tile,flip))
3102 reset_draw = true;
3103 if(refl_flags & (1<<REFL_90CW))
3104 if(__pixel_draw(15-y,x,tile,flip))
3105 reset_draw = true;
3106 if(refl_flags & (1<<REFL_90CCW))
3107 if(__pixel_draw(y,15-x,tile,flip))
3108 reset_draw = true;
3109 }
3110 select_mode = tmp_sel_mode;
3111 }
3112
3113 if(reset_draw)
3114 drawing = 0;
3115 redraw=true;
3116 }
3117
3118 if(gui_mouse_b()==0)
3119 {
3120 bdown=false;
3121 drawing=0;
3122 }
3123
3124 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3125 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3126
3127 {
3128 tile_x=temp_x;
3129 tile_y=temp_y;
3130 redraw=true;
3131 }
3132
3133 const char *toolnames[t_max]=
3134 {
3135 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3136 };
3137
3138 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3139 if(toolbtn > -1 && toolbtn < t_max)
3140 {
3141 int32_t column = toolbtn%tool_btns.w;
3142 int32_t row = toolbtn/tool_btns.w;
3143
3144 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3145 redraw=true;
3146 }
3147 /* Highlight the hovered pixel? Eh, maybe too much?
3148 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3149 if(hov_pix > -1)
3150 {
3151 int32_t column = hov_pix%zoomtile.w;
3152 int32_t row = hov_pix/zoomtile.w;
3153
3154 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3155 redraw=true;
3156 }*/
3157
3158 if(redraw)
3159 {
3160 draw_edit_scr(tile,flip,cs,oldtile, false);
3161 anim_hw_screen();
3162 }
3163 else
3164 {
3165 bool hs=has_selection();
3166
3167 if(hs)
3168 {
3169 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3170 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3171 anim_hw_screen();
3172 }
3173
3174 update_tool_cursor();
3175 }
3176 }
3177 while(!done);
3178
3179 unfloat_selection();
3180 clear_selection_grid();
3181
3182 while(gui_mouse_b()) rest(1);
3183
3184 if(done==1)
3185 {
3186 for(int32_t i=0; i<undocount; i++)
3187 {
3188 newtilebuf[tile].data[i]=oldtile[i];
3189 }
3190 }
3191 else
3192 {
3193 byte *buf = new byte[undocount];
3194
3195 // put back old tile
3196 for(int32_t i=0; i<undocount; i++)
3197 {
3198 buf[i] = newtilebuf[tile].data[i];
3199 newtilebuf[tile].data[i] = oldtile[i];
3200 }
3201
3202 // go
3203 go_tiles();
3204
3205 // replace old tile with new one again
3206 for(int32_t i=0; i<undocount; i++)
3207 {
3208 newtilebuf[tile].data[i] = buf[i];
3209 }
3210
3211 mark_save_dirty();
3212
3213 if(buf!=NULL)
3214 {
3215 delete[] buf;
3216 }
3217 }
3218
3219 MouseSprite::set(ZQM_NORMAL);
3220 register_blank_tiles();
3221 register_used_tiles();
3222 clear_tooltip();
3223 destroy_bitmap(selection_pattern);
3224 destroy_bitmap(selecting_pattern);
3225 destroy_bitmap(intersection_pattern);
3226 font = oldfont;
3227 popup_zqdialog_end();
3228 }
3229
3230 /* Grab Tile Code */
3231
3232 enum recolorState { rcNone, rc4Bit, rc8Bit };
3233
3234 BITMAP* original_imagebuf_bitmap=NULL;
3235 void *imagebuf=NULL;
3236 int32_t imagebuf_bitmap_scale=0;
3237 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3238 int32_t imagesize=0;
3239 int32_t tilecount=0;
3240 int32_t imagetype=0;
3241 int32_t imagex,imagey,selx,sely;
3242 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3243 bool nesmode=false;
3244 int32_t grabmask=0;
3245 recolorState recolor=rcNone;
3246 PALETTE imagepal;
3247
3248 /* bestfit_color:
3249 * Searches a palette for the color closest to the requested R, G, B value.
3250 */
3251 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3252 {
3253 int32_t bestMatch = 0; // Color with the lowest total difference so far
3254 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3255 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3256
3257 for(int32_t i = 0; i < CSET_SIZE; i++)
3258 {
3259 byte *rgbByte;
3260
3261 // This seems to be right...
3262 if(cs==2 || cs==3 || cs==4)
3263 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3264 else if(cs==9)
3265 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3266 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3267 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3268 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3269 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3270 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3271 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3272 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3273 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3274 else
3275 rgbByte = colordata + (CSET(cs)+i)*3;
3276
3277 int32_t dr=r-*rgbByte;
3278 int32_t dg=g-*(rgbByte+1);
3279 int32_t db=b-*(rgbByte+2);
3280
3281 // Track both the total color difference and the single greatest
3282 // difference of R, G, B. The idea is that it's better to have
3283 // two or three small differences than one big one.
3284 // The differences are multiplied by different numbers to account
3285 // for the differences in perceived brightness of the three colors.
3286 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3287 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3288
3289 // Perfect match? Just stop here.
3290 if(totalDiff==0)
3291 return i;
3292
3293 if(totalDiff < bestTotalDiff || // Best match so far?
3294 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3295 {
3296 bestMatch=i;
3297 bestTotalDiff=totalDiff;
3298 bestHighDiff=highDiff;
3299 }
3300 }
3301
3302 return bestMatch;
3303 }
3304
3305 // Same as the above, but draws from all colors in CSets 0-11.
3306 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3307 {
3308 int32_t bestMatch = 0;
3309 float bestTotalDiff = 100000;
3310 float bestHighDiff = 100000;
3311
3312 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3313 {
3314 byte *rgbByte;
3315
3316 int32_t cs=i>>4;
3317 if(cs==2 || cs==3 || cs==4)
3318 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3319 else if(cs==9)
3320 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3321 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3322 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3323 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3324 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3325 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3326 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3327 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3328 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3329 else
3330 rgbByte = colordata + i * 3;
3331
3332 int32_t dr=r-*rgbByte;
3333 int32_t dg=g-*(rgbByte+1);
3334 int32_t db=b-*(rgbByte+2);
3335
3336 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3337 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3338
3339 if(totalDiff==0) // Perfect match?
3340 return i;
3341
3342 if(totalDiff < bestTotalDiff || // Best match so far?
3343 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3344 {
3345 bestMatch=i;
3346 bestTotalDiff=totalDiff;
3347 bestHighDiff=highDiff;
3348 }
3349 }
3350
3351 return bestMatch;
3352 }
3353
3354 byte cset_reduce_table[PAL_SIZE];
3355
3356 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3357 {
3358 for(int32_t i=0; i<PAL_SIZE; i++)
3359 {
3360 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3361 }
3362 }
3363
3364 void calc_cset_reduce_table_8bit(PALETTE pal)
3365 {
3366 for(int32_t i=0; i<PAL_SIZE; i++)
3367 {
3368 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3369 }
3370 }
3371
3372 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3373 {
3374 //storage space for the grabbed image
3375 byte buf[64];
3376 memset(buf,0,64);
3377 byte *oldsrc=src;
3378
3379 //for 8 lines in the source image...
3380 for(int32_t line=0; line<(nesmode?4:8); line++)
3381 {
3382 //bx is the pixel at the start of a line in the storage buffer
3383 int32_t bx=line<<(nesmode?4:3);
3384 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3385 byte b=src[(bp&1)?line:line<<1];
3386
3387 //fill the storage buffer with data from the source image
3388 for(int32_t i=7; i>=0; --i)
3389 {
3390 buf[bx+i] = (b&1)+(cs<<4);
3391 b>>=1;
3392 }
3393 }
3394
3395 ++src;
3396
3397 for(int32_t p=1; p<bp; p++)
3398 {
3399 for(int32_t line=0; line<(nesmode?4:8); line++)
3400 {
3401 int32_t bx=line<<(nesmode?4:3);
3402 byte b=src[(bp&1)?line:line<<1];
3403
3404 for(int32_t i=7; i>=0; --i)
3405 {
3406 if(nesmode)
3407 {
3408 buf[bx+8+i] = (b&1)+(cs<<4);
3409 }
3410 else
3411 {
3412 buf[bx+i] |= (b&1)<<p;
3413 }
3414
3415 b>>=1;
3416 }
3417 }
3418
3419 if(p&1)
3420 {
3421 src+=15;
3422 }
3423 else
3424 {
3425 ++src;
3426 }
3427 }
3428
3429
3430 if(nesmode)
3431 {
3432 src=oldsrc;
3433
3434 for(int32_t counter=0; counter<2; ++counter, ++src)
3435 {
3436 //for 8 lines in the source image...
3437 for(int32_t line=0; line<4; line++)
3438 {
3439 //bx is the pixel at the start of a line in the storage buffer
3440 int32_t bx=line<<4;
3441 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3442 byte b=src[(line+4)<<1];
3443
3444 //fill the storage buffer with data from the source image
3445 for(int32_t i=7; i>=0; --i)
3446 {
3447 // buf[bx+i] = (b&1)+(cs<<4);
3448 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3449 b>>=1;
3450 }
3451 }
3452 }
3453 }
3454
3455 int32_t c=0;
3456
3457 switch(romtilemode)
3458 {
3459 case 0:
3460 case 1:
3461 case 2:
3462 for(int32_t j=0; j<8; j++)
3463 {
3464 for(int32_t i=0; i<8; i++)
3465 {
3466 putpixel(dest,x+i,y+j,buf[c++]);
3467 }
3468 }
3469
3470 break;
3471
3472 case 3:
3473 for(int32_t j=0; j<4; j++)
3474 {
3475 for(int32_t i=0; i<16; i++)
3476 {
3477 putpixel(dest,x+i,y+j,buf[c++]);
3478 }
3479 }
3480
3481 break;
3482 }
3483 }
3484
3485 const char *file_type[ftMAX]=
3486 {
3487 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3488 };
3489
3490 void draw_grab_window()
3491 {
3492 int w = 640;
3493 int h = 480;
3494 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3495 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3496 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3497 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3498
3499 FONT *oldfont = font;
3500 font = get_zc_font(font_lfont);
3501 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3502 font=oldfont;
3503 }
3504
3505 void draw_grab_scr(int32_t tile, int32_t cs, byte *newtile,int32_t black, byte *newformat, BITMAP* screen3)
3506 {
3507
3508 int32_t yofs=0;
3509 //clear_to_color(screen2,bg);
3510 clear_bitmap(screen3);
3511 rectfill(screen2, 0, 0, 319, 159, black);
3512 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3513 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3514 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3515 yofs=3;
3516
3517 // text_mode(-1);
3518 int32_t tileromcolumns=20;
3519
3520 switch(imagetype)
3521 {
3522 case ftBMP:
3523 if(recolor==rcNone)
3524 {
3525 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3526 }
3527 else
3528 {
3529 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3530 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3531
3532 for(int32_t y=0; y<maxy; y++)
3533 {
3534 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3535 {
3536 break;
3537 }
3538
3539 for(int32_t x=0; x<maxx; x++)
3540 {
3541 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3542 {
3543 break;
3544 }
3545
3546 if(recolor==rc8Bit)
3547 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3548 else
3549 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3550 }
3551 }
3552 }
3553
3554 break;
3555
3556 case ftZGP:
3557 case ftQST:
3558 case ftZQT:
3559 case ftQSU:
3560 case ftTIL:
3561 {
3562 tiledata *hold = newtilebuf;
3563 newtilebuf = grabtilebuf;
3564 //fixme
3565 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3566 int32_t t=imagey*TILES_PER_ROW;
3567
3568 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3569 {
3570 if(t <= tilecount)
3571 {
3572 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3573 }
3574
3575 ++t;
3576 }
3577
3578 newtilebuf = hold;
3579 //fixme
3580 }
3581 break;
3582
3583 case ftBIN:
3584 {
3585 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3586 byte *buf = (byte*)imagebuf;
3587
3588 switch(romtilemode)
3589 {
3590 case 0:
3591 for(int32_t y=0; y<160; y+=8)
3592 {
3593 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3594 {
3595 puttileROM(screen2,x,y,buf+ofs,cs);
3596 ofs+=8*bp;
3597 }
3598 }
3599
3600 for(int32_t y=0; y<160; y+=8)
3601 {
3602 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3603 {
3604 puttileROM(screen2,x+128,y,buf+ofs,cs);
3605 ofs+=8*bp;
3606 }
3607 }
3608
3609 break;
3610
3611 case 1:
3612 for(int32_t y=0; y<160; y+=16)
3613 {
3614 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3615 {
3616 puttileROM(screen2,x,y,buf+ofs,cs);
3617 ofs+=8*bp;
3618 puttileROM(screen2,x,y+8,buf+ofs,cs);
3619 ofs+=8*bp;
3620 }
3621 }
3622
3623 for(int32_t y=0; y<160; y+=16)
3624 {
3625 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3626 {
3627 puttileROM(screen2,x+128,y,buf+ofs,cs);
3628 ofs+=8*bp;
3629 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3630 ofs+=8*bp;
3631 }
3632 }
3633
3634 break;
3635
3636 case 2:
3637 for(int32_t y=0; y<160; y+=16)
3638 {
3639 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3640 {
3641 puttileROM(screen2,x,y,buf+ofs,cs);
3642 ofs+=8*bp;
3643 puttileROM(screen2,x+8,y,buf+ofs,cs);
3644 ofs+=8*bp;
3645 puttileROM(screen2,x,y+8,buf+ofs,cs);
3646 ofs+=8*bp;
3647 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3648 ofs+=8*bp;
3649 }
3650 }
3651
3652 for(int32_t y=0; y<160; y+=16)
3653 {
3654 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3655 {
3656 puttileROM(screen2,x+128,y,buf+ofs,cs);
3657 ofs+=8*bp;
3658 puttileROM(screen2,x+136,y,buf+ofs,cs);
3659 ofs+=8*bp;
3660 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3661 ofs+=8*bp;
3662 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3663 ofs+=8*bp;
3664 }
3665 }
3666
3667 break;
3668
3669 case 3:
3670 for(int32_t y=0; y<160; y+=16)
3671 {
3672 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3673 {
3674 puttileROM(screen2,x,y,buf+ofs,cs);
3675 ofs+=8*bp;
3676 puttileROM(screen2,x,y+4,buf+ofs,cs);
3677 ofs+=8*bp;
3678 puttileROM(screen2,x,y+8,buf+ofs,cs);
3679 ofs+=8*bp;
3680 puttileROM(screen2,x,y+12,buf+ofs,cs);
3681 ofs+=8*bp;
3682 }
3683 }
3684
3685 for(int32_t y=0; y<160; y+=16)
3686 {
3687 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3688 {
3689 puttileROM(screen2,x+128,y,buf+ofs,cs);
3690 ofs+=8*bp;
3691 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3692 ofs+=8*bp;
3693 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3694 ofs+=8*bp;
3695 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3696 ofs+=8*bp;
3697 }
3698 }
3699
3700 break;
3701 }
3702 }
3703 break;
3704 }
3705
3706 tiledata hold;
3707 bool holdblank = blank_tile_table[0];
3708
3709 if(is_valid_format(newtilebuf[0].format))
3710 {
3711 hold.format = newtilebuf[0].format;
3712 hold.data = (byte *)malloc(tilesize(hold.format));
3713 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3714 }
3715 else
3716 {
3717 hold.format=tfInvalid;
3718 hold.data=NULL;
3719 }
3720
3721 newtilebuf[0].format=newformat[0];
3722 blank_tile_table[0] = false;
3723
3724 if(newtilebuf[0].data!=NULL)
3725 {
3726 free(newtilebuf[0].data);
3727 }
3728
3729 if(is_valid_format(newtilebuf[0].format))
3730 {
3731 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3732
3733 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3734 {
3735 newtilebuf[0].data[i]=newtile[i];
3736 }
3737 }
3738 else
3739 {
3740 newtilebuf[0].data=NULL;
3741 }
3742
3743 puttile16(screen2,0,208,168+yofs,cs,0);
3744 overtile16(screen2,0,232,168+yofs,cs,0);
3745 newtilebuf[0].format=hold.format;
3746 blank_tile_table[0] = holdblank;
3747
3748 if(newtilebuf[0].data!=NULL)
3749 {
3750 free(newtilebuf[0].data);
3751 }
3752
3753 if(is_valid_format(newtilebuf[0].format))
3754 {
3755 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3756
3757 for(int32_t i=0; i<256; i++)
3758 {
3759 newtilebuf[0].data[i]=hold.data[i];
3760 }
3761 }
3762 else
3763 {
3764 newtilebuf[0].data=NULL;
3765 }
3766
3767 if(hold.data!=NULL)
3768 {
3769 free(hold.data);
3770 }
3771
3772 puttile16(screen2,tile,208,192+yofs,cs,0);
3773 overtile16(screen2,tile,232,192+yofs,cs,0);
3774
3775 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3776 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3777 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3778 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3779
3780 // rect(screen2,183,167,200,184,dvc(7*2));
3781 // rect(screen2,207,167,224,184,dvc(7*2));
3782 // rect(screen2,231,167,248,184,dvc(7*2));
3783 // rect(screen2,207,191,224,208,dvc(7*2));
3784 // rect(screen2,231,191,248,208,dvc(7*2));
3785
3786 /*
3787 rect(screen2,183,167,200,184,vc(14));
3788 rect(screen2,207,167,224,184,vc(14));
3789 rect(screen2,231,167,248,184,vc(14));
3790 rect(screen2,207,191,224,208,vc(14));
3791 rect(screen2,231,191,248,208,vc(14));
3792 */
3793 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3794 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3795 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3796 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3797 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3798 int32_t screen_xofs=6;
3799 int32_t screen_yofs=25;
3800 int winh = 511;
3801 int32_t mul = 2;
3802
3803 yofs = 0;
3804
3805 stretch_blit(screen2,screen3,0,0,320,240,0,0,640,480);
3806
3807 // Suspend the current font while draw_text_button does its work
3808 FONT* oldfont = font;
3809
3810 font = get_zc_font(font_lfont_l);
3811
3812 int txt_x = 4;
3813 int rbtn_x = 512, lbtn_x = 236;
3814 int max_fpath_wid = rbtn_x-2-txt_x;
3815 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3816 // Interface
3817 switch(imagetype)
3818 {
3819 case 0:
3820 textprintf_ex(screen3,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3821 break;
3822
3823 case ftBMP:
3824 {
3825 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3826 int text_x = txt_x;
3827 int text_y = (216 + yofs) * mul;
3828 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3829 // int text_w = text_length(font, text.c_str());
3830 // int text_h = text_height(font);
3831 // static int grab_scale_tooltip_id = ttip_register_id();
3832 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3833 textprintf_ex(screen3, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3834
3835 draw_text_button(screen3,lbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3836 break;
3837 }
3838
3839 case ftZGP:
3840 case ftQST:
3841 case ftZQT:
3842 case ftQSU:
3843 case ftTIL:
3844 case ftBIN:
3845 textprintf_ex(screen3,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3846 break;
3847 }
3848
3849 textprintf_ex(screen3,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3850 textprintf_ex(screen3,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3851
3852 if(bp==8)
3853 textprintf_ex(screen3,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3854 else
3855 textprintf_ex(screen3,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3856 textprintf_ex(screen3,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3857
3858 if(imagetype==ftBIN)
3859 {
3860 textprintf_ex(screen3,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3861 textprintf_ex(screen3,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3862 textprintf_ex(screen3,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3863 }
3864
3865 int fpath_y = (224+yofs)*mul;
3866 if(text_length(font,imagepath) <= max_fpath_wid)
3867 textout_ex(screen3,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3868 else
3869 {
3870 char buf[2052] = {0};
3871 strncpy(buf,imagepath,2048);
3872 int len = strlen(buf);
3873 char *ptr = buf;
3874 char *endptr = buf+len;
3875 char *it = endptr;
3876 int tmpy = fpath_y;
3877 int tmph = text_height(font)+1;
3878 while(true)
3879 {
3880 if(tmpy+tmph > (winh-2))
3881 break; //Out of space!
3882 char c = *it;
3883 bool end = !c;
3884 *it = 0;
3885 int newlen = text_length(font,ptr);
3886 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3887 {
3888 if(end) //No stored character, string ended
3889 {
3890 textout_ex(screen3,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3891 break;
3892 }
3893 char t[5];
3894 t[0] = c;
3895 for(int q = 1; q < 5; ++q)
3896 t[q] = it[q];
3897 strcpy(it,"...");
3898 textout_ex(screen3,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3899 for(int q = 0; q < 5; ++q)
3900 it[q] = t[q];
3901 tmpy += tmph;
3902 ptr = it;
3903 it = endptr;
3904 }
3905 else
3906 {
3907 *it = c;
3908 --it;
3909 }
3910 }
3911 }
3912 draw_text_button(screen3,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3913 draw_text_button(screen3,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3914 draw_text_button(screen3,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3915 draw_text_button(screen3,lbtn_x,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3916
3917 font = oldfont;
3918 }
3919
3920 COLOR_MAP imagepal_table;
3921
3922
3923 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3924 {
3925 //these are here to bypass compiler warnings about unused arguments
3926 x=x;
3927
3928 rgb->r = pal[y].r;
3929 rgb->g = pal[y].g;
3930 rgb->b = pal[y].b;
3931 }
3932
3933
3934 void load_imagebuf()
3935 {
3936 PACKFILE *f;
3937 //cache QRS
3938 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3939 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3940 // {
3941 // cached_rules[q] = quest_rules[q];
3942 // }
3943 bool compressed=false;
3944 bool encrypted=false;
3945 tiledata *hold=newtilebuf;
3946 zquestheader tempheader{};
3947
3948 if(imagebuf)
3949 {
3950 switch(imagetype)
3951 {
3952 case ftBMP:
3953 if (original_imagebuf_bitmap != imagebuf)
3954 destroy_bitmap((BITMAP*)imagebuf);
3955 destroy_bitmap(original_imagebuf_bitmap);
3956 break;
3957
3958 case ftZGP:
3959 case ftQST:
3960 case ftZQT:
3961 case ftQSU:
3962 case ftTIL:
3963 clear_tiles(grabtilebuf);
3964 break;
3965
3966 case ftBIN:
3967 free(imagebuf);
3968 break;
3969 }
3970
3971 imagebuf=NULL;
3972 original_imagebuf_bitmap=NULL;
3973 }
3974
3975 selx=sely=romofs=0;
3976 bp=4;
3977 imagetype=filetype(imagepath);
3978
3979 dword section_id;
3980 word section_version;
3981
3982 switch(imagetype)
3983 {
3984 case ftBMP:
3985 packfile_password("");
3986 memset(imagepal, 0, sizeof(PALETTE));
3987 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
3988 imagesize = file_size_ex_password(imagepath,"");
3989 tilecount=0;
3990
3991 RGB_MAP tmp_rgb_table;
3992 create_rgb_table(&tmp_rgb_table, imagepal, NULL);
3993 rgb_map = &tmp_rgb_table;
3994 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
3995
3996 if(!original_imagebuf_bitmap)
3997 {
3998 imagetype=0;
3999 }
4000 else
4001 {
4002 imagebuf = original_imagebuf_bitmap;
4003 imagebuf_bitmap_scale = 1;
4004 }
4005
4006 break;
4007
4008 case ftBIN:
4009 packfile_password("");
4010 imagesize = file_size_ex_password(imagepath, "");
4011 tilecount=0;
4012
4013 if(imagesize)
4014 {
4015 imagebuf = malloc(imagesize);
4016
4017 if(!readfile(imagepath,imagebuf,imagesize))
4018 {
4019 free(imagebuf);
4020 imagesize=0;
4021 imagetype=0;
4022 }
4023 }
4024
4025 break;
4026
4027 case ftTIL:
4028 packfile_password("");
4029 imagesize = file_size_ex_password(imagepath,"");
4030 f = pack_fopen_password(imagepath,F_READ,"");
4031
4032 if(!f)
4033 {
4034 goto error;
4035 }
4036
4037 if(!p_mgetl(&section_id,f))
4038 {
4039 goto error;
4040 }
4041
4042 if(section_id==ID_TILES)
4043 {
4044 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4045 {
4046 goto error;
4047 }
4048 }
4049
4050 error:
4051 pack_fclose(f);
4052 tilecount=count_tiles(grabtilebuf);
4053 break;
4054
4055 case ftZGP:
4056 packfile_password("");
4057 imagesize = file_size_ex_password(imagepath, "");
4058 f=pack_fopen_password(imagepath,F_READ,"");
4059
4060 if(!f)
4061 {
4062 goto error2;
4063 }
4064
4065 if(!p_mgetl(&section_id,f))
4066 {
4067 goto error2;
4068 }
4069
4070 if(section_id!=ID_GRAPHICSPACK)
4071 {
4072 goto error2;
4073 }
4074
4075 //section version info
4076 if(!p_igetw(&section_version,f))
4077 {
4078 goto error2;
4079 }
4080
4081 if(!read_deprecated_section_cversion(f))
4082 {
4083 goto error2;
4084 }
4085
4086 //tiles
4087 if(!p_mgetl(&section_id,f))
4088 {
4089 goto error2;
4090 }
4091
4092 if(section_id==ID_TILES)
4093 {
4094 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4095 {
4096 goto error2;
4097 }
4098 }
4099
4100 error2:
4101 pack_fclose(f);
4102 tilecount=count_tiles(grabtilebuf);
4103 break;
4104
4105 case ftQST:
4106 encrypted=true;
4107 case ftZQT:
4108 compressed=true;
4109 case ftQSU:
4110 packfile_password("");
4111 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4112 newtilebuf=grabtilebuf;
4113 byte skip_flags[4];
4114
4115 for(int32_t i=0; i<skip_max; ++i)
4116 {
4117 set_bit(skip_flags,i,1);
4118 }
4119
4120 set_bit(skip_flags,skip_tiles,0);
4121 set_bit(skip_flags,skip_header,0);
4122 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4123 if (ret)
4124 {
4125 imagetype=0;
4126 imagesize=0;
4127 clear_tiles(grabtilebuf);
4128 chop_path(imagepath);
4129 }
4130
4131 if (!ret && encrypted && compressed)
4132 {
4133 if(quest_access(imagepath, &tempheader) != 1)
4134 {
4135 imagetype=0;
4136 imagesize=0;
4137 clear_tiles(grabtilebuf);
4138 chop_path(imagepath);
4139 }
4140 }
4141
4142 //setPackfilePassword(NULL);
4143 newtilebuf=hold;
4144 tilecount=count_tiles(grabtilebuf);
4145 break;
4146 }
4147
4148 rgb_map = zq_rgb_table;
4149 //restore cashed QRs / rules
4150
4151 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4152 // {
4153 // quest_rules[q] = cached_rules[q];
4154 // }
4155 }
4156
4157 static char bitstrbuf[32];
4158 bool leeching_from_tiles=false;
4159
4160 const char *bitlist(int32_t index, int32_t *list_size)
4161 {
4162 int32_t imported=2;
4163
4164 if(index>=0)
4165 {
4166 bound(index,0,leeching_from_tiles?2:1);
4167
4168 if(index==imported)
4169 {
4170 sprintf(bitstrbuf,"Imported");
4171 }
4172 else
4173 {
4174 sprintf(bitstrbuf,"%d",4<<index);
4175 }
4176
4177 return bitstrbuf;
4178 }
4179
4180 *list_size=leeching_from_tiles?3:2;
4181 return NULL;
4182 }
4183
4184 12 static ListData bit_list(bitlist, &font);
4185
4186 static DIALOG leech_dlg[] =
4187 {
4188 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4189 12 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4190 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4191 // 2
4192 12 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4193 12 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4194 12 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4195 // 5
4196 12 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4197 12 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4198 12 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4199 12 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4200 //9
4201 12 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4202 12 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4203
4204 12 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4205 12 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4206 12 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4207 12 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4208 12 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4209 //16
4210 12 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4211 12 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4212 12 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4213
4214 12 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4215 12 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4216 12 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4217
4218 12 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4219 12 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4220 12 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4221
4222 12 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4223 12 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4224 12 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4225
4226 12 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4227 12 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4228 12 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4229 12 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4230 12 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4231 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4232 };
4233
4234 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4235 {
4236 bool shift=true; // fix this!
4237 int32_t cst=0;
4238 int32_t currtile=start;
4239 int32_t height=0, width=0;
4240 byte *testtile = new byte[tilesize(tf32Bit)];
4241 byte imported_format=0;
4242 char updatestring[6];
4243 bool canadd;
4244 bool temp_canadd;
4245 bool duplicate;
4246 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4247 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4248 {
4249 0,0,0,0
4250 };
4251 BITMAP *status;
4252 status = create_bitmap_ex(8,240,140);
4253 clear_bitmap(status);
4254 sprintf(updatestring, "%d", LeechUpdate);
4255 leech_dlg[0].dp2=get_zc_font(font_lfont);
4256 leech_dlg[6].dp=updatestring;
4257
4258 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4259
4260 for(int32_t i=0; i<2; i++)
4261 {
4262 leech_dlg[i+7].flags=0;
4263 }
4264
4265 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4266
4267 for(int32_t i=0; i<12; i++)
4268 {
4269 leech_dlg[i+16].flags=0;
4270 }
4271
4272 for(int32_t i=0; i<4; i++)
4273 {
4274 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4275 }
4276
4277 leech_dlg[31].d1=0;
4278
4279 large_dialog(leech_dlg);
4280
4281 int32_t ret = do_zqdialog(leech_dlg,3);
4282
4283 if(ret==2)
4284 {
4285 delete[] testtile;
4286 return false;
4287 }
4288
4289 int32_t cdepth=leech_dlg[31].d1+1;
4290 int32_t newformat=0;
4291 auto lu = atoi(updatestring);
4292 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4293 if(LeechUpdate!=lu)
4294 {
4295 LeechUpdate=lu;
4296 zc_set_config("zquest","leech_update",LeechUpdate);
4297 }
4298 if(LeechUpdateTiles!=lut)
4299 {
4300 LeechUpdateTiles=lut;
4301 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4302 }
4303
4304 int32_t old_dupe[4];
4305 for(int32_t j=0; j<4; j++)
4306 {
4307 old_dupe[j] = DuplicateAction[j];
4308 for(int32_t i=0; i<3; i++)
4309 {
4310 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4311 {
4312 DuplicateAction[j]=i;
4313 }
4314 }
4315 }
4316 if(old_dupe[0] != DuplicateAction[0])
4317 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4318 if(old_dupe[1] != DuplicateAction[1])
4319 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4320 if(old_dupe[2] != DuplicateAction[2])
4321 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4322 if(old_dupe[3] != DuplicateAction[3])
4323 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4324
4325 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4326 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4327 {
4328 OnlyCheckNewTilesForDuplicates=ocntfd;
4329 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4330 }
4331
4332 leeching_from_tiles=false;
4333
4334 switch(imagetype)
4335 {
4336 case ftBIN:
4337 width=imagesize/128;
4338 height=1;
4339 break;
4340
4341 case ftZGP:
4342 case ftQST:
4343 case ftZQT:
4344 case ftQSU:
4345 case ftTIL:
4346 leeching_from_tiles=true;
4347 width=count_tiles(grabtilebuf);
4348 height=1;
4349 break;
4350
4351 case ftBMP:
4352 width=((((BITMAP*)imagebuf)->w)+15)/16;
4353 height=((((BITMAP*)imagebuf)->h)+15)/16;
4354 break;
4355 }
4356
4357 if(currtile+(width*height)>NEWMAXTILES)
4358 {
4359 if (!alert_confirm("Confirm Truncation","Too many tiles. Truncation may occur."))
4360 {
4361 delete[] testtile;
4362 return false;
4363 }
4364 }
4365
4366 go_tiles();
4367 mark_save_dirty();
4368
4369 for(int32_t ty=0; ty<height; ty++) //for every row
4370 {
4371 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4372 {
4373 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4374 {
4375 FONT *oldfont = font;
4376 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4377 static bool created_tbar=false;
4378 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4379
4380 if(created_tbar)
4381 {
4382 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4383 }
4384 else
4385 {
4386 font = get_zc_font(font_lfont);
4387 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4388 font = oldfont;
4389 created_tbar=true;
4390 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4391 }
4392
4393 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4394 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4395 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4396 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4397 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4398 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4399 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4400 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4401 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4402 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4403 blit(status,screen,0, 0, 40, 20, 240, 140);
4404 }
4405
4406 canadd=true;
4407
4408 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4409 {
4410 delete[] testtile;
4411 return true;
4412 }
4413
4414 switch(imagetype)
4415 {
4416 case ftBIN:
4417 break;
4418
4419 case ftZGP:
4420 case ftQST:
4421 case ftZQT:
4422 case ftQSU:
4423 case ftTIL:
4424 memset(testtile, 0, tilesize(tf32Bit));
4425 imported_format=grabtilebuf[tx].format;
4426
4427 switch(cdepth)
4428 {
4429 case 1: //4-bit
4430 newformat=tf4Bit;
4431
4432 switch(imported_format)
4433 {
4434 case tf4Bit:
4435 case tf8Bit:
4436 for(int32_t y=0; y<16; y++) //snag a tile
4437 {
4438 for(int32_t x=0; x<16; x+=2)
4439 {
4440 testtile[(y*8)+(x/2)]=
4441 (grabtilebuf[tx].data[y*16+x]&15)+
4442 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4443 }
4444 }
4445
4446 break;
4447 }
4448
4449 break;
4450
4451 case 2: //8-bit
4452 newformat=tf8Bit;
4453
4454 switch(imported_format)
4455 {
4456 case tf4Bit:
4457 unpack_tile(grabtilebuf, tx, 0, true);
4458 cst = cs&15;
4459 cst <<= CSET_SHFT;
4460
4461 for(int32_t i=0; i<256; i++)
4462 {
4463 if(!shift||unpackbuf[i]!=0)
4464 {
4465 unpackbuf[i]+=cst;
4466 }
4467 }
4468
4469 pack_tiledata(testtile, unpackbuf, tf8Bit);
4470 break;
4471
4472 case tf8Bit:
4473 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4474 break;
4475 }
4476
4477 break;
4478
4479 case 3: //original tile's bit depth
4480 newformat=imported_format;
4481 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4482 break;
4483 }
4484
4485 break;
4486
4487 case ftBMP:
4488 newformat=cdepth;
4489
4490 for(int32_t y=0; y<16; y++) //snag a tile
4491 {
4492 for(int32_t x=0; x<16; x+=2)
4493 {
4494 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4495 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4496 }
4497 }
4498
4499 break;
4500 }
4501
4502 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4503 {
4504 temp_canadd=true;
4505
4506 //check all tiles before this one
4507 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4508 {
4509 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4510 {
4511 if(DuplicateAction[flipping]>0)
4512 {
4513 if(keypressed())
4514 {
4515 delete[] testtile;
4516 return true;
4517 }
4518
4519 duplicate=(newformat==imported_format);
4520
4521 if(duplicate)
4522 {
4523 switch(flipping)
4524 {
4525 case 0: //normal
4526 if(dest[checktile].data!=NULL)
4527 {
4528 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4529 {
4530 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4531 {
4532 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4533 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4534 {
4535 duplicate=false;
4536 }
4537 }
4538 }
4539 }
4540
4541 break;
4542
4543 case 1: //horizontal
4544 if(dest[checktile].data!=NULL)
4545 {
4546 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4547 {
4548 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4549 {
4550 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4551 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4552 {
4553 duplicate=false;
4554 }
4555 }
4556 }
4557 }
4558
4559 break;
4560
4561 case 2: //vertical
4562 if(dest[checktile].data!=NULL)
4563 {
4564 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4565 {
4566 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4567 {
4568 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4569 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4570 {
4571 duplicate=false;
4572 }
4573 }
4574 }
4575 }
4576
4577 break;
4578
4579 case 3: //both
4580 if(dest[checktile].data!=NULL)
4581 {
4582 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4583 {
4584 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4585 {
4586 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4587 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4588 {
4589 duplicate=false;
4590 }
4591 }
4592 }
4593 }
4594
4595 break;
4596 }
4597 }
4598
4599 if(duplicate==true)
4600 {
4601 ++duplicates_found[flipping];
4602 ++total_duplicates_found;
4603
4604 if(DuplicateAction[flipping]>1)
4605 {
4606 ++total_duplicates_discarded;
4607 temp_canadd=false;
4608 }
4609 }
4610 }
4611
4612 canadd=canadd&&temp_canadd;
4613 }
4614 }
4615 }
4616
4617 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4618 dest[currtile].format=newformat;
4619
4620 if(dest[currtile].data!=NULL)
4621 {
4622 free(dest[currtile].data);
4623 }
4624
4625 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4626
4627 if(dest[currtile].data==NULL)
4628 {
4629 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4630 }
4631
4632 if(canadd==true)
4633 {
4634 /*
4635 for(int32_t y=0; y<16; y++)
4636 {
4637 for(int32_t x=0; x<8; x++)
4638 {
4639 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4640 }
4641 }
4642 */
4643 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4644 ++currtile;
4645 }
4646 }
4647 }
4648
4649 destroy_bitmap(status);
4650 delete[] testtile;
4651 return true;
4652 }
4653
4654 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4655 {
4656 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4657 byte format=defFormat;
4658 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4659
4660 switch(imagetype)
4661 {
4662 case ftZGP:
4663 case ftQST:
4664 case ftZQT:
4665 case ftQSU:
4666 case ftTIL:
4667 case ftBIN:
4668 case ftBMP:
4669 for(int32_t ty=0; ty<height; ty++)
4670 {
4671 for(int32_t tx=0; tx<width; tx++)
4672 {
4673 format=defFormat;
4674 switch(imagetype)
4675 {
4676 case ftZGP:
4677 case ftQST:
4678 case ftZQT:
4679 case ftQSU:
4680 case ftTIL:
4681 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4682 break;
4683 }
4684
4685 bool ever_did_unmasked = false;
4686
4687 for(int32_t y=0; y<16; y++)
4688 {
4689 for(int32_t x=0; x<16; x+=2)
4690 {
4691 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4692 if (masked)
4693 {
4694 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4695 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4696 }
4697 else
4698 {
4699 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4700 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4701 ever_did_unmasked = true;
4702 }
4703 if (format == tf4Bit)
4704 {
4705 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4706 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4707 }
4708 }
4709 }
4710
4711 if (ever_did_unmasked)
4712 newformat[(ty*TILES_PER_ROW)+tx] = format;
4713 }
4714 }
4715
4716 break;
4717
4718 default:
4719 for(int32_t i=0; i<200; i++)
4720 {
4721 for(int32_t j=0; j<256; j++)
4722 {
4723 dest[i][j]=0;
4724 }
4725
4726 newformat[i] = tf4Bit;
4727 }
4728
4729 break;
4730 }
4731 }
4732
4733 static void scale_imagebuf_bitmap()
4734 {
4735 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4736
4737 float scale = IMAGEBUF_SCALE;
4738 int nw = original_imagebuf_bitmap->w * scale;
4739 int nh = original_imagebuf_bitmap->h * scale;
4740 if (nw <= 0 || nh <= 0)
4741 return;
4742
4743 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4744 if (!scaled_bmp)
4745 return;
4746
4747 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4748 if (imagebuf != original_imagebuf_bitmap)
4749 destroy_bitmap((BITMAP*)imagebuf);
4750 imagebuf = scaled_bmp;
4751 }
4752
4753 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4754 void grab_tile(int32_t tile,int32_t &cs)
4755 {
4756 zq_allow_tile_draw_cache = true;
4757
4758 int window_w = 640+6+6, window_h = 480+25+6;
4759 int window_x=(zq_screen_w-window_w)/2;
4760 int window_y=(zq_screen_h-window_h)/2;
4761 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4762 int window_xofs = 0;
4763 int screen_xofs=6;
4764 int screen_yofs=25;
4765 int panel_yofs=0;
4766 int bwidth = 61*1.5;
4767 int bheight = 20*1.5;
4768 int button_x = 512 + 6;
4769 int grab_ok_button_y = 168*2 + 32 - 7;
4770 int leech_button_x = 117*2 + 7;
4771 int leech_button_y = 166*2 + 32 - 7;
4772 int grab_cancel_button_y = 192*2 + 32 - 7;
4773 int file_button_y = 216*2 + 32 - 7;
4774 int rec_button_x = 117*2 + 6;
4775 int rec_button_y = 192*2 + 32 - 7;
4776
4777 int screen_y1 = 24;
4778 int screen_y2 = screen_y1+320-1;
4779
4780 int crect_x = 184+190;
4781 int crect_y = 168*2 + 32;
4782 int crect_w = 8*2;
4783 int crect_h = 8*2;
4784
4785 int xrect_x = 640 + 12 - 21;
4786 int xrect_y = 5;
4787
4788 byte newtile[200][256];
4789 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4790 clear_bitmap(screen3);
4791 byte newformat[200];
4792
4793 memset(newtile, 0, 200*256);
4794 memset(newformat, 0, 200);
4795
4796 static EXT_LIST list[] =
4797 {
4798 { (char *)"All Files (*.*)", NULL },
4799 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4800 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4801 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4802 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4803 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4804 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4805 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4806 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4807 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4808 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4809 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4810 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4811 { NULL, NULL }
4812 };
4813
4814
4815 memset(cset_reduce_table, 0, 256);
4816 memset(col_diff,0,3*128);
4817 bool bdown=false;
4818 int done=0;
4819 int pal=0;
4820 int black=vc(0),white=vc(15);
4821 int selwidth=1, selheight=1;
4822 int selx2=0, sely2=0;
4823 bool xreversed=false, yreversed=false;
4824 bool doleech=false, dofile=false, dopal=false;
4825
4826 int jwin_pal2[jcMAX];
4827 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4828
4829 if(imagebuf==NULL)
4830 load_imagebuf();
4831
4832 calc_cset_reduce_table(imagepal, cs);
4833 calc_cset_reduce_table_8bit(imagepal);
4834 draw_grab_window();
4835 draw_grab_scr(tile, cs, newtile[0], black, newformat, screen3);
4836 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4837
4838 auto do_anim = [&](bool redraw)
4839 {
4840 if (!(framecnt%8))
4841 redraw = true;
4842 if(redraw)
4843 {
4844 draw_grab_scr(tile, cs, newtile[0], black, newformat, screen3);
4845
4846 if(framecnt&8)
4847 rect(screen3, selx*2, sely*2,
4848 selx*2+((selwidth-1)*32)+(32-1), sely*2+((selheight-1)*32)+(32-1), white);
4849
4850 blit(screen3,screen,0,0,0+screen_xofs,0+screen_yofs,window_w-2*screen_xofs,window_h-2*screen_yofs);
4851 }
4852 anim_hw_screen();
4853 };
4854 while(gui_mouse_b()) rest(1);
4855
4856 do_anim(true);
4857 do
4858 {
4859 HANDLE_CLOSE_ZQDLG();
4860 if(exiting_program) break;
4861 //rest(4);
4862 bool redraw = false;
4863
4864 if(keypressed())
4865 {
4866 switch(readkey()>>8)
4867 {
4868 case KEY_F:
4869 dofile=true;
4870 break;
4871
4872 case KEY_L:
4873 doleech=true;
4874 break;
4875
4876 case KEY_P:
4877 if(imagetype==ftBMP)
4878 {
4879 dopal=true;
4880 recolor=rcNone;
4881 calc_cset_reduce_table(imagepal, cs);
4882 }
4883
4884 break;
4885
4886 case KEY_ESC:
4887 done=1;
4888 break;
4889
4890 case KEY_ENTER_PAD:
4891 case KEY_ENTER:
4892 done=2;
4893 break;
4894
4895 case KEY_DOWN:
4896 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4897 else ++imagey;
4898
4899 break;
4900
4901 case KEY_UP:
4902 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4903 else --imagey;
4904
4905 break;
4906
4907 case KEY_RIGHT:
4908 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4909 else ++imagex;
4910
4911 break;
4912
4913 case KEY_LEFT:
4914 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4915 else --imagex;
4916
4917 break;
4918
4919 case KEY_PGDN:
4920 imagey+=10;
4921 break;
4922
4923 case KEY_PGUP:
4924 imagey-=10;
4925 break;
4926
4927 case KEY_HOME:
4928 imagex=imagey=0;
4929 break;
4930
4931 case KEY_EQUALS:
4932 case KEY_PLUS_PAD:
4933 cs = (cs<13) ? cs+1:0;
4934 if(recolor==rc4Bit)
4935 calc_cset_reduce_table(imagepal, cs);
4936 break;
4937
4938 case KEY_MINUS:
4939 case KEY_MINUS_PAD:
4940 cs = (cs>0) ? cs-1:13;
4941 if(recolor==rc4Bit)
4942 calc_cset_reduce_table(imagepal, cs);
4943 break;
4944
4945 case KEY_S:
4946 if(grabmode==1) grabmode=8;
4947 else if(grabmode==8) grabmode=16;
4948 else grabmode=1;
4949
4950 break;
4951
4952 case KEY_COMMA:
4953 if (imagetype == ftBMP)
4954 {
4955 imagebuf_bitmap_scale--;
4956 if (imagebuf_bitmap_scale == 0)
4957 imagebuf_bitmap_scale = -2;
4958 scale_imagebuf_bitmap();
4959 }
4960 break;
4961 case KEY_STOP:
4962 if (imagetype == ftBMP)
4963 {
4964 imagebuf_bitmap_scale++;
4965 if (imagebuf_bitmap_scale == -1)
4966 imagebuf_bitmap_scale = 1;
4967 scale_imagebuf_bitmap();
4968 }
4969 break;
4970
4971 case KEY_1:
4972 if(recolor==rc8Bit)
4973 recolor=rcNone;
4974 //imagex=(imagex*bp)>>3;
4975 bp=1;
4976 //imagex<<=3;
4977 nesmode=false;
4978 break;
4979
4980 case KEY_2:
4981 if(recolor==rc8Bit)
4982 recolor=rcNone;
4983 //imagex=(imagex*bp)>>3;
4984 bp=2;
4985 //imagex<<=2;
4986 nesmode=false;
4987 break;
4988
4989 case KEY_N:
4990 if(recolor==rc8Bit)
4991 recolor=rcNone;
4992 //imagex=(imagex*bp)>>3;
4993 bp=2;
4994 //imagex<<=2;
4995 nesmode=true;
4996 break;
4997
4998 case KEY_4:
4999 if(recolor==rc8Bit)
5000 recolor=rcNone;
5001 //imagex=(imagex*bp)>>3;
5002 bp=4;
5003 //imagex<<=1;
5004 nesmode=false;
5005 break;
5006
5007 case KEY_8:
5008 //imagex=(imagex*bp)>>3;
5009 bp=8;
5010 break;
5011
5012 case KEY_B:
5013 if(bp==2&&!nesmode)
5014 {
5015 nesmode=true;
5016 }
5017 else
5018 {
5019 nesmode=false;
5020 bp<<=1;
5021
5022 if(bp==16)
5023 {
5024 bp=1;
5025 //imagex<<=3;
5026 }
5027 else
5028 {
5029 //imagex>>=1;
5030 }
5031 }
5032
5033 break;
5034
5035 case KEY_M:
5036 romtilemode=(romtilemode+1)%4;
5037 break;
5038
5039 case KEY_Z:
5040 if(romofs>0) --romofs;
5041
5042 break;
5043
5044 case KEY_X:
5045 ++romofs;
5046 break;
5047
5048 case KEY_R:
5049 if(pal)
5050 {
5051 dopal=true;
5052 }
5053
5054 if(recolor!=rcNone)
5055 recolor=rcNone;
5056 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5057 {
5058 bp=8;
5059 recolor=rc8Bit;
5060 calc_cset_reduce_table_8bit(imagepal);
5061 }
5062 else
5063 {
5064 if(bp==8)
5065 bp=4;
5066 recolor=rc4Bit;
5067 calc_cset_reduce_table(imagepal, cs);
5068 }
5069 break;
5070 }
5071
5072 clear_keybuf();
5073
5074 if(imagex<0) imagex=0;
5075
5076 if(imagey<0) imagey=0;
5077
5078 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5079
5080 do_anim(true);
5081 continue;
5082 }
5083
5084 //boogie!
5085 if(gui_mouse_b()==1 && !bdown)
5086 {
5087 int x=gui_mouse_x();
5088 int y=gui_mouse_y();
5089 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5090 if(do_x_button(screen, xrect_x, xrect_y))
5091 done=1;
5092
5093 if(!bdown)
5094 {
5095 bool regrab=false;
5096 bdown=true;
5097 FONT* oldfont = font;
5098 font = get_zc_font(font_lfont_l);
5099
5100 if(y>=screen_y1 && y<=screen_y2)
5101 {
5102 do
5103 {
5104 HANDLE_CLOSE_ZQDLG();
5105 if(exiting_program) break;
5106 int x = (gui_mouse_x()-screen_xofs) / 2;
5107 int y = (gui_mouse_y()-screen_yofs) / 2;
5108
5109 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5110
5111 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5112 {
5113 selx=vbound((x/grabmode)*grabmode,0,304);
5114 sely=vbound((y/grabmode)*grabmode,0,144);
5115 selx2=selx;
5116 sely2=sely;
5117 selwidth=1;
5118 selheight=1;
5119 xreversed=false;
5120 yreversed=false;
5121 }
5122 else
5123 {
5124 if(xreversed)
5125 {
5126 zc_swap(selx, selx2);
5127 xreversed=false;
5128 }
5129
5130 if(yreversed)
5131 {
5132 zc_swap(sely, sely2);
5133 yreversed=false;
5134 }
5135
5136 selx2=vbound((x/grabmode)*grabmode,0,304);
5137 sely2=vbound((y/grabmode)*grabmode,0,144);
5138 selwidth=1+(abs(selx2-selx))/16;
5139 selheight=1+(abs(sely2-sely))/16;
5140
5141 if(selx2<selx)
5142 {
5143 zc_swap(selx, selx2);
5144 xreversed=true;
5145 }
5146
5147 if(sely2<sely)
5148 {
5149 zc_swap(sely, sely2);
5150 yreversed=true;
5151 }
5152 }
5153
5154 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5155
5156 if(changed || !(framecnt%8))
5157 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5158 do_anim(changed);
5159 }
5160 while(gui_mouse_b());
5161 font = oldfont;
5162 continue;
5163 }
5164 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5165 {
5166 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5167 done=2;
5168 }
5169 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5170 {
5171 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5172 {
5173 doleech=true;
5174 }
5175 }
5176 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5177 {
5178 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5179 done=1;
5180 }
5181 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5182 {
5183 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5184 {
5185 dofile=true;
5186 }
5187 }
5188 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5189 {
5190 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5191 {
5192 if(pal)
5193 {
5194 dopal = true;
5195 }
5196
5197 if(recolor!=rcNone)
5198 recolor=rcNone;
5199 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5200 {
5201 bp=8;
5202 recolor=rc8Bit;
5203 calc_cset_reduce_table_8bit(imagepal);
5204 }
5205 else
5206 {
5207 if(bp==8)
5208 bp=4;
5209 recolor=rc4Bit;
5210 calc_cset_reduce_table(imagepal, cs);
5211 }
5212 }
5213 }
5214 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5215 {
5216 regrab=true;
5217 grabmask^=1;
5218 }
5219 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5220 {
5221 regrab=true;
5222 grabmask^=2;
5223 }
5224 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5225 {
5226 regrab=true;
5227 grabmask^=4;
5228 }
5229 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5230 {
5231 regrab=true;
5232 grabmask^=8;
5233 }
5234
5235 font = oldfont;
5236
5237 if(regrab)
5238 {
5239 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5240 do_anim(true);
5241 continue;
5242 }
5243 }
5244 }
5245
5246 if(gui_mouse_b()==0)
5247 bdown=false;
5248
5249 if(dofile)
5250 {
5251 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5252 {
5253 zc_set_palette(RAMpal);
5254 pal=0;
5255 white=vc(15);
5256 black=vc(0);
5257 strcpy(imagepath,temppath);
5258 load_imagebuf();
5259 imagex=imagey=0;
5260 calc_cset_reduce_table(imagepal, cs);
5261 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5262 }
5263
5264 while(key[KEY_ESC])
5265 {
5266 poll_keyboard();
5267 /* do nothing */
5268 rest(1);
5269 }
5270
5271 clear_keybuf();
5272 dofile = false;
5273 do_anim(true);
5274 continue;
5275 }
5276
5277 if(doleech)
5278 {
5279 if(leech_tiles(newtilebuf,tile,cs))
5280 {
5281 done=1;
5282 }
5283 else
5284 {
5285 while(key[KEY_ESC])
5286 {
5287 poll_keyboard();
5288 /* do nothing */
5289 rest(1);
5290 }
5291
5292 clear_keybuf();
5293 redraw = true;
5294 }
5295
5296 doleech = false;
5297 }
5298
5299 if(dopal)
5300 {
5301 pal^=1;
5302
5303 if(pal)
5304 {
5305 get_bw(imagepal,black,white);
5306
5307 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5308 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5309 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5310 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5311 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5312 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5313 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5314 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5315 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5316 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5317 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5318 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5319 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5320 gui_bg_color=jwin_pal[jcBOX];
5321 gui_fg_color=jwin_pal[jcBOXFG];
5322 jwin_set_colors(jwin_pal);
5323 }
5324 else
5325 {
5326 white=vc(15);
5327 black=vc(0);
5328
5329 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5330 gui_bg_color=jwin_pal[jcBOX];
5331 gui_fg_color=jwin_pal[jcBOXFG];
5332 jwin_set_colors(jwin_pal);
5333 }
5334
5335 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5336
5337 dopal = false;
5338 redraw = true;
5339 }
5340
5341 do_anim(redraw);
5342 }
5343 while(!done);
5344
5345 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5346 gui_bg_color=jwin_pal[jcBOX];
5347 gui_fg_color=jwin_pal[jcBOXFG];
5348 jwin_set_colors(jwin_pal);
5349
5350
5351 if(done==2)
5352 {
5353 go_tiles();
5354 mark_save_dirty();
5355
5356 for(int y=0; y<selheight; y++)
5357 {
5358 for(int x=0; x<selwidth; x++)
5359 {
5360 int temptile=tile+((TILES_PER_ROW*y)+x);
5361 int format=(bp==8) ? tf8Bit : tf4Bit;
5362
5363 if(newtilebuf[temptile].data!=NULL)
5364 free(newtilebuf[temptile].data);
5365
5366 newtilebuf[temptile].format=format;
5367 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5368
5369 if(newtilebuf[temptile].data==NULL)
5370 {
5371 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5372 break;
5373 }
5374
5375 for(int i=0; i<256; i++)
5376 {
5377 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5378 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5379 }
5380
5381 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5382 }
5383 }
5384 }
5385
5386 destroy_bitmap(screen3);
5387
5388 if(pal)
5389 zc_set_palette(RAMpal);
5390
5391 recolor=rcNone;
5392 calc_cset_reduce_table(imagepal, cs);
5393 register_blank_tiles();
5394 popup_zqdialog_end();
5395
5396 zq_allow_tile_draw_cache = false;
5397 }
5398
5399 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5400 bool tile_is_used(int32_t tile)
5401 {
5402 return used_tile_table[tile];
5403 }
5404 void draw_tiles(int32_t first,int32_t cs)
5405 {
5406 draw_tiles(screen2, first, cs, true);
5407 }
5408 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, bool large, bool true_empty)
5409 {
5410 clear_bitmap(dest);
5411 BITMAP *buf = create_bitmap_ex(8,16,16);
5412
5413 int32_t w = 16;
5414 int32_t h = 16;
5415
5416 if(large)
5417 {
5418 w *=2;
5419 h *=2;
5420 }
5421
5422 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5423 {
5424 int32_t x = (i%TILES_PER_ROW)<<4;
5425 int32_t y = (i/TILES_PER_ROW)<<4;
5426 int32_t l = 16;
5427
5428 if(large)
5429 {
5430 x*=2;
5431 y*=2;
5432 l*=2;
5433 }
5434
5435 l-=2;
5436
5437 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5438 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5439 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5440 {
5441 if(!true_empty) //Use pure color 0; no effects
5442 {
5443 if (InvalidBG == 2)
5444 {
5445 draw_checkerboard(dest, x, y, w);
5446 }
5447 else if(InvalidBG == 1)
5448 {
5449 draw_static(dest, x, y, l+1, l+1);
5450 }
5451 else
5452 {
5453 for(int32_t dy=0; dy<=l+1; dy++)
5454 {
5455 for(int32_t dx=0; dx<=l+1; dx++)
5456 {
5457 dest->line[dy+(y)][dx+(x)]=vc(0);
5458 }
5459 }
5460 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5461 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5462 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5463 }
5464 }
5465 }
5466 else
5467 {
5468 puttile16(buf,first+i,0,0,cs,0);
5469 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5470 }
5471
5472 if((framecnt%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5473 {
5474 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((framecnt%32)/6)+10),-1,"8");
5475 }
5476 }
5477
5478 destroy_bitmap(buf);
5479 }
5480
5481 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5482 {
5483 int32_t yofs=3;
5484 BITMAP *buf = create_bitmap_ex(8,16,16);
5485 int32_t mul = 2;
5486 FONT *tfont = get_zc_font(font_pfont);
5487
5488 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5489 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5490 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5491 tfont = get_zc_font(font_lfont_l);
5492
5493 // Copied tile and numbers
5494 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5495 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5496 if(copy>=0)
5497 {
5498 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5499 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5500
5501 if(copycnt>1)
5502 {
5503 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5504 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5505 }
5506 else
5507 {
5508 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5509 }
5510 }
5511 else // No tiles copied
5512 {
5513 if (InvalidBG == 2)
5514 {
5515 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5516 }
5517 else if(InvalidBG == 1)
5518 {
5519 draw_static(screen2, 36*mul, 216*mul+yofs, 16*mul, 16*mul);
5520 }
5521 else
5522 {
5523 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5524 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5525 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5526 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5527 }
5528 }
5529
5530
5531 // Current tile
5532 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5533 puttile16(buf,tile,0,0,cs,0);
5534 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5535
5536 // Current selection mode
5537 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5538 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5539
5540 if(tile>tile2)
5541 {
5542 zc_swap(tile,tile2);
5543 }
5544
5545 char tbuf[8];
5546 tbuf[0]=0;
5547
5548 if(tile2!=tile)
5549 {
5550 sprintf(tbuf,"-%d",tile2);
5551 }
5552
5553 // Current tile and CSet text
5554 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5555 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5556 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5557
5558 FONT *tf = font;
5559 font = tfont;
5560
5561 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5562 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5563 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5564 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5565 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5566
5567 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5568 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5569 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5570 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5571
5572 font = tf;
5573
5574 int32_t w = 640;
5575 int32_t h = 480;
5576 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5577 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5578 int32_t screen_xofs=window_xofs+6;
5579 int32_t screen_yofs=window_yofs+25;
5580
5581 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5582 }
5583
5584 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5585 {
5586 int32_t yofs=3;
5587 BITMAP *buf = create_bitmap_ex(8,16,16);
5588 int32_t mul = 2;
5589 FONT *tfont = get_zc_font(font_pfont);
5590
5591 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5592 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5593 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5594 tfont = get_zc_font(font_lfont_l);
5595
5596 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5597
5598 if(copy>=0)
5599 {
5600 puttile16(buf,copy,0,0,cs,flip);
5601 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5602 }
5603 else
5604 {
5605 if (InvalidBG == 2)
5606 {
5607 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5608 }
5609 else if(InvalidBG == 1)
5610 {
5611 draw_static(screen2, 124*mul, 216*mul+yofs, 16*mul, 16*mul);
5612 }
5613 else
5614 {
5615 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5616 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5617 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5618 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5619 }
5620 }
5621
5622 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5623 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5624 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5625
5626 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5627 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5628
5629 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5630 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5631
5632 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5633 {
5634 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5635 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5636 }
5637
5638 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5639 puttile16(buf,tile,0,0, cs,
5640 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5641 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5642
5643 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5644 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5645 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5646 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5647
5648 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5649 {
5650 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5651 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5652 }
5653
5654 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5655 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5656 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5657 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5658
5659
5660 int32_t w = 640;
5661 int32_t h = 480;
5662 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5663 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5664 int32_t screen_xofs=window_xofs+6;
5665 int32_t screen_yofs=window_yofs+25;
5666
5667 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5668 }
5669 /*
5670 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5671 {
5672 buf[t].format=format;
5673 if (buf[t].data!=NULL)
5674 {
5675 free(buf[t].data);
5676 }
5677 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5678 if (buf[t].data==NULL)
5679 {
5680 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5681 }
5682 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5683 {
5684 buf[t].data[i]=0;
5685 }
5686 }
5687 */
5688
5689 int32_t hide_used()
5690 {
5691 show_only_unused_tiles ^= 1;
5692 return D_O_K;
5693 }
5694 int32_t hide_unused()
5695 {
5696 show_only_unused_tiles ^= 2;
5697 return D_O_K;
5698 }
5699 int32_t hide_blank()
5700 {
5701 show_only_unused_tiles ^= 4;
5702 return D_O_K;
5703 }
5704 int32_t hide_8bit_marker()
5705 {
5706 show_only_unused_tiles ^= 8;
5707 return D_O_K;
5708 }
5709
5710 enum
5711 {
5712 MENUID_SELTILE_VIEW_HIDE_USED,
5713 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5714 MENUID_SELTILE_VIEW_HIDE_BLANK,
5715 MENUID_SELTILE_VIEW_HIDE_8BIT,
5716 };
5717
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_view_menu
5718 60 {
5719
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5720
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5721
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5722
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5723 };
5724
5725 12 static std::function<void(int)> select_tile_color_depth_cb;
5726
5727 static void set_tile_color_depth_4()
5728 {
5729 select_tile_color_depth_cb(tf4Bit);
5730 }
5731 static void set_tile_color_depth_8()
5732 {
5733 select_tile_color_depth_cb(tf8Bit);
5734 }
5735 enum
5736 {
5737 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5738 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5739 };
5740
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_color_depth_menu
5741 36 {
5742
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5743
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5744 };
5745
5746 //returns the row the tile is in on its page
5747 int32_t tile_page_row(int32_t tile)
5748 {
5749 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5750 }
5751
5752 enum {ti_none, ti_encompass, ti_broken};
5753
5754 //striped check and striped selection
5755 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5756 {
5757 int32_t cmb_first = cmb.o_tile;
5758 int32_t cmb_last = cmb.o_tile;
5759 do
5760 {
5761 cmb_last = cmb.tile;
5762 animate(cmb, true);
5763 }
5764 while(cmb.tile != cmb.o_tile);
5765 reset_combo_animation(cmb);
5766 cmb_first += offset;
5767 cmb_last += offset;
5768
5769 if(cmb_first > selection_last || cmb_last < selection_first)
5770 return ti_none;
5771 if(cmb_first >= selection_first && cmb_last <= selection_last)
5772 return ti_encompass;
5773
5774 do
5775 {
5776 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5777 {
5778 reset_combo_animation(cmb);
5779 return ti_broken; //contained, but non-encompassing.
5780 }
5781 animate(cmb, true);
5782 }
5783 while(cmb.tile != cmb.o_tile);
5784 reset_combo_animation(cmb);
5785 return ti_none;
5786 }
5787 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5788 {
5789 // if selection is before or after check...
5790 if((check_first>selection_last)||(selection_first>check_last))
5791 {
5792 return ti_none;
5793 }
5794
5795 // if selection envelopes check
5796 if((selection_first<=check_first)&&(selection_last>=check_last))
5797 {
5798 return ti_encompass; //encompass
5799 }
5800
5801 //everything else is a break
5802 return ti_broken; //intersect
5803 }
5804
5805
5806
5807 //rectangular check and striped selection
5808 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5809 {
5810 int32_t ret1=-1, ret2=-1;
5811
5812 for(int32_t i=0; i<check_height; ++i)
5813 {
5814 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5815 int32_t check_last=check_first+check_width-1;
5816 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5817
5818 if(ret2==ti_broken)
5819 {
5820 return ti_broken;
5821 }
5822
5823 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5824 }
5825
5826 if(ret1==ti_encompass)
5827 {
5828 if((TILEROW(selection_first)<=check_top) &&
5829 (TILEROW(selection_last)>=(check_top+check_height-1)))
5830 {
5831 return ti_encompass;
5832 }
5833 else
5834 {
5835 return ti_broken;
5836 }
5837 }
5838
5839 return ti_none;
5840 }
5841
5842
5843 //striped check and rectangular selection
5844 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5845 {
5846 if(selection_width < TILES_PER_ROW)
5847 {
5848 int32_t cmb_first = cmb.o_tile;
5849 int32_t cmb_last = cmb.o_tile;
5850 do
5851 {
5852 cmb_last = cmb.tile;
5853 animate(cmb, true);
5854 }
5855 while(cmb.tile != cmb.o_tile);
5856 reset_combo_animation(cmb);
5857 cmb_first += offset;
5858 cmb_last += offset;
5859
5860 if((TILEROW(cmb_first)>=selection_top) &&
5861 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5862 (TILECOL(cmb_first)>=selection_left) &&
5863 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5864 {
5865 return ti_encompass;
5866 }
5867 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5868 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5869 {
5870 return ti_none;
5871 }
5872
5873 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5874 {
5875 int32_t firstcol = TILECOL(cmb_first);
5876 int32_t lastcol = TILECOL(cmb_last);
5877
5878 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5879 return ti_none;
5880 else //handle skip x
5881 {
5882 do
5883 {
5884 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5885 {
5886 reset_combo_animation(cmb);
5887 return ti_broken;
5888 }
5889 animate(cmb, true);
5890 }
5891 while(cmb.tile != cmb.o_tile);
5892 reset_combo_animation(cmb);
5893 return ti_none;
5894 }
5895 }
5896 else //multi-row combo...
5897 {
5898 int32_t row = TILEROW(cmb_first);
5899
5900 do
5901 {
5902 if(row < selection_top || row > selection_top+selection_height-1)
5903 {
5904 //This row isn't in the selection; skip to next row
5905 do
5906 {
5907 animate(cmb,true);
5908 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5909 }
5910 while(TILEROW(cmb.tile) == row);
5911 row = TILEROW(cmb.tile);
5912 continue;
5913 }
5914
5915 //This row IS in the selection; check each tile.
5916 do
5917 {
5918 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5919 {
5920 reset_combo_animation(cmb);
5921 return ti_broken;
5922 }
5923 animate(cmb, true);
5924 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5925 }
5926 while(TILEROW(cmb.tile) == row);
5927 row = TILEROW(cmb.tile);
5928 }
5929 while(cmb.tile != cmb.o_tile);
5930
5931 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5932 }
5933 }
5934
5935 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
5936 }
5937 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
5938 {
5939 if(selection_width < TILES_PER_ROW)
5940 {
5941 if((check_last-check_first+1<=selection_width) &&
5942 (TILEROW(check_first)>=selection_top) &&
5943 (TILEROW(check_last)<=selection_top+selection_height-1) &&
5944 (TILECOL(check_first)>=selection_left) &&
5945 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
5946 {
5947 return ti_encompass;
5948 }
5949 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
5950 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5951 {
5952 return ti_none;
5953 }
5954
5955 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
5956
5957 //one last base case: the strip we're interested in only lies along one row
5958 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
5959 {
5960 int32_t cfcol = check_first%TILES_PER_ROW;
5961 int32_t clcol = check_last%TILES_PER_ROW;
5962
5963 if(clcol < selection_left || cfcol >= selection_left+selection_width)
5964 return ti_none;
5965 else
5966 return ti_broken;
5967 }
5968 else
5969 {
5970 //recursively cut the strip into substrips which lie entirely on one row
5971 int32_t currow = check_first/TILES_PER_ROW;
5972 int32_t endrow = check_last/TILES_PER_ROW;
5973 int32_t accum = 0;
5974 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
5975
5976 for(++currow; currow<endrow; currow++)
5977 {
5978 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
5979 }
5980
5981 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
5982
5983 if(accum > 0)
5984 return ti_broken;
5985
5986 return ti_none;
5987 }
5988 }
5989
5990 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
5991 }
5992
5993 //rectangular check and rectangular selection
5994 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
5995 {
5996 if((check_left>=selection_left) &&
5997 (check_left+check_width<=selection_left+selection_width) &&
5998 (check_top>=selection_top) &&
5999 (check_top+check_height<=selection_top+selection_height))
6000 {
6001 return ti_encompass;
6002 }
6003 else
6004 {
6005 for(int32_t i=check_top; i<check_top+check_height; ++i)
6006 {
6007 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6008 {
6009 return ti_broken;
6010 }
6011 }
6012 }
6013
6014 return ti_none;
6015 }
6016
6017
6018
6019
6020 static DIALOG move_textbox_list_dlg[] =
6021 {
6022 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6023 12 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6024 12 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6025 12 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6026 12 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6027 12 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6028 12 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6029 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6030 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6031 };
6032
6033 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6034 {
6035 char buf1[512] = {0};
6036 char buf2[512] = {0};
6037 large_dialog(move_textbox_list_dlg);
6038 DIALOG& tbox = move_textbox_list_dlg[3];
6039 {
6040 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6041 int indx = 0, word_indx = 0;
6042 for(char c : msg)
6043 {
6044 if(c == ' ' || c == '\n')
6045 word_indx = indx;
6046 buf1[indx++] = c;
6047 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6048 {
6049 buf1[word_indx] = 0;
6050 strcpy(buf2, msg.c_str()+word_indx+1);
6051 break;
6052 }
6053 }
6054 }
6055
6056 move_textbox_list_dlg[0].dp = (void*)title;
6057 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6058 move_textbox_list_dlg[1].dp = buf1;
6059 move_textbox_list_dlg[2].dp = buf2;
6060 tbox.dp = textbox;
6061 tbox.d2 = 0;
6062 auto tby = tbox.y;
6063 auto tbh = tbox.h;
6064 if(!buf2[0])
6065 {
6066 auto diff = move_textbox_list_dlg[2].h;
6067 tbox.y -= diff;
6068 tbox.h += diff;
6069 }
6070
6071 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6072 position_mouse_z(0);
6073 tbox.y = tby;
6074 tbox.h = tbh;
6075
6076 return ret == 4;
6077 }
6078
6079 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6080 {
6081 return a==0?b:a==1?c:d;
6082 }
6083
6084 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6085 {
6086 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6087 int i = ti_none;
6088 auto t = ref->getTile() + ref->offset();
6089
6090 if(combo_ref)
6091 {
6092 if(proc.rect)
6093 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6094 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6095 }
6096 else if(proc.rect)
6097 {
6098 if(ref->h > 1)
6099 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6100 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6101 }
6102 else
6103 {
6104 if(ref->h > 1)
6105 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6106 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6107 }
6108
6109 bool in = i != ti_none, out = i != ti_encompass;
6110 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6111 {
6112 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6113 if(proc.rect)
6114 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6115 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6116 if(i != ti_none)
6117 in = true;
6118 if(i != ti_encompass)
6119 out = true;
6120 }
6121 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6122
6123 if(i != ti_none && ref->getTile() != 0)
6124 {
6125 if(mode == Mode::CHECK_ALL)
6126 {
6127 move_refs.emplace_back(std::move(ref));
6128 return true;
6129 }
6130 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6131 {
6132 if(warning_flood || warning_list.tellp() >= 65000)
6133 {
6134 if(!warning_flood)
6135 warning_list << "...\n...\n...\nmany others";
6136 warning_flood = true;
6137 }
6138 else
6139 warning_list << ref->name << '\n';
6140 }
6141 else if(i==ti_encompass)
6142 {
6143 move_refs.emplace_back(std::move(ref));
6144 return true;
6145 }
6146 }
6147 return false;
6148 }
6149
6150 bool TileMoveList::check_prot()
6151 {
6152 if(!TileProtection)
6153 return true;
6154 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6155
6156 warning_flood = false;
6157 warning_list.clear();
6158
6159 return ret;
6160 }
6161
6162 void TileMoveList::add_diff(int diff)
6163 {
6164 for(auto& ref : move_refs)
6165 ref->addTile(diff);
6166 }
6167
6168 //from 'combo.h'
6169 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6170 {
6171 int i = ti_none;
6172 auto c = ref->getCombo();
6173
6174 if(ref->no_move)
6175 processed_combos[c] = true;
6176 else processed_combos[c]; //inserts element if does not exist
6177 i = move_intersection_ss(c, c, proc._first, proc._last);
6178
6179 if(i != ti_none && ref->getCombo() != 0)
6180 {
6181 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6182 {
6183 if(ComboProtection)
6184 {
6185 if(warning_flood || warning_list.tellp() >= 65000)
6186 {
6187 if(!warning_flood)
6188 warning_list << "...\n...\n...\nmany others";
6189 warning_flood = true;
6190 }
6191 else
6192 warning_list << ref->name << '\n';
6193 }
6194 }
6195 else if(i==ti_encompass)
6196 {
6197 move_refs.emplace_back(std::move(ref));
6198 return true;
6199 }
6200 }
6201 return false;
6202 }
6203
6204 bool ComboMoveList::check_prot()
6205 {
6206 if(!ComboProtection)
6207 return true;
6208 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6209 bool subset_header = false;
6210 for(int q = 0; q < 2; ++q)
6211 {
6212 bool is_dest = (q==1);
6213 if(!is_dest && !source_process)
6214 continue;
6215 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6216 for(auto it = subset.begin(); it != subset.end();)
6217 {
6218 auto s = *it;
6219 if(warning_flood || warning_list.tellp() >= 65000)
6220 {
6221 if(!warning_flood)
6222 warning_list << "...\n...\n...\nmany others";
6223 warning_flood = true;
6224 break;
6225 }
6226 set<int> in_set, out_set;
6227 bool no_move = is_dest;
6228 for(int c : *s)
6229 {
6230 int i = move_intersection_ss(c, c, proc._first, proc._last);
6231 if(i != ti_none)
6232 in_set.insert(c);
6233 if(i != ti_encompass)
6234 out_set.insert(c);
6235 if(!no_move)
6236 {
6237 auto it = processed_combos.find(c);
6238 if(it != processed_combos.end() && it->second)
6239 no_move = true;
6240 }
6241 }
6242 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6243 if(i == ti_encompass && !no_move)
6244 {
6245 it = subset.erase(it);
6246 continue;
6247 }
6248 if(i == ti_none)
6249 {
6250 ++it;
6251 continue;
6252 }
6253
6254 if(!subset_header)
6255 {
6256 subset_header = true;
6257 warning_list << "===== Broken Relative Combo Groups =====\n";
6258 }
6259 bool comma = false;
6260 warning_list << "In(";
6261 for(int c : in_set)
6262 {
6263 if(comma)
6264 warning_list << ",";
6265 else comma = true;
6266 warning_list << c;
6267 }
6268 warning_list << "),Out(";
6269 comma = false;
6270 for(int c : out_set)
6271 {
6272 if(comma)
6273 warning_list << ",";
6274 else comma = true;
6275 warning_list << c;
6276 }
6277 warning_list << ")\n";
6278 it = subset.erase(it);
6279 }
6280 }
6281 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6282
6283 processed_combos.clear();
6284 warning_flood = false;
6285 warning_list.clear();
6286
6287 return ret;
6288 }
6289
6290 void ComboMoveList::add_diff(int diff)
6291 {
6292 for(auto& ref : move_refs)
6293 ref->addCombo(diff);
6294 }
6295
6296 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6297 {
6298 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6299 {
6300 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6301 }
6302 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6303 {
6304 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6305 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6306 }
6307 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6308 {
6309 list.add_tile(&w->tile, "McGuffin Piece");
6310 }
6311 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6312 {
6313 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6314 }
6315 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6316 {
6317 if (w->tile == -1)
6318 return;
6319
6320 list.add_tile(&w->tile, "MiniTile");
6321 }
6322 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6323 {
6324 int fr = w->frames ? w->frames : 1;
6325 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6326 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6327 fr = (fr/4_zf).getCeil();
6328
6329 for(auto q = 0; q < 4; ++q)
6330 {
6331 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6332 }
6333 }
6334 }
6335
6336 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6337 {
6338 for(auto q = 0; q < page.contents.size(); ++q)
6339 {
6340 size_t indx = list.move_refs.size();
6341 collect_subscreen_tiles(*page.contents[q], list);
6342 for(; indx < list.move_refs.size(); ++indx)
6343 {
6344 auto& ref = list.move_refs[indx];
6345 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6346 }
6347 }
6348 }
6349
6350 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6351 {
6352 for (auto q = 0; q < subscreen.pages.size(); ++q)
6353 {
6354 size_t indx = list.move_refs.size();
6355 collect_subscreen_tiles(subscreen.pages[q], list);
6356 for(; indx < list.move_refs.size(); ++indx)
6357 {
6358 auto& ref = list.move_refs[indx];
6359 ref->name = fmt::format("Page {} - {}", q, ref->name);
6360 }
6361 }
6362 }
6363
6364 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6365 {
6366 bool BSZ2 = get_qr(qr_BSZELDA);
6367 bool move = source_process.has_value();
6368 TileMoveUndo local_undo;
6369 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6370 auto& vec = storage.vec;
6371 storage.diff = diff;
6372 storage.state = false;
6373
6374 //Combos
6375 {
6376 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6377 dest_process, source_process, mode,
6378 move
6379 ? "The tiles used by the following combos will be partially cleared by the move."
6380 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6381 ));
6382 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6383 {
6384 auto& cmb = combobuf[q];
6385 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6386 : fmt::format(" ({})", cmb.label));
6387 movelist->add_combo(&cmb, lbl);
6388
6389 //type-specific
6390 char const* type_name = ZI.getComboTypeName(cmb.type);
6391 switch(cmb.type)
6392 {
6393 case cSPOTLIGHT:
6394 {
6395 if(!(cmb.usrflags & cflag1))
6396 break;
6397 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6398 break;
6399 }
6400 }
6401 }
6402 if(!every_proc && !movelist->check_prot())
6403 return false;
6404 }
6405 //Items
6406 {
6407 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6408 dest_process, source_process, mode,
6409 move
6410 ? "The tiles used by the following items will be partially cleared by the move."
6411 : "The tiles used by the following items will be partially or completely overwritten by this process."
6412 ));
6413 build_bii_list(false);
6414 for(int32_t u=0; u<MAXITEMS; u++)
6415 {
6416 auto id = bii[u].i;
6417 itemdata& itm = itemsbuf[id];
6418 if(itm.type == itype_bottle)
6419 {
6420 vector<std::tuple<int,int,int>> rects;
6421 auto fr = itm.frames;
6422 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6423 {
6424 bottletype const& bt = QMisc.bottle_types[q];
6425 if(bt.is_blank())
6426 continue;
6427 rects.emplace_back(fr+q*fr, fr, 1);
6428 }
6429 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6430 false, 0, 0, rects);
6431 }
6432 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6433 }
6434 if(!every_proc && !movelist->check_prot())
6435 return false;
6436 }
6437 //Weapon sprites
6438 {
6439 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6440 dest_process, source_process, mode,
6441 move
6442 ? "The tiles used by the following weapons will be partially cleared by the move."
6443 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6444 ));
6445 build_biw_list();
6446
6447 for(int32_t u=0; u<MAXWPNS; u++)
6448 {
6449 bool ignore_frames=false;
6450 int32_t m=0;
6451
6452 auto id = biw[u].i;
6453 auto& wpn = wpnsbuf[id];
6454
6455 switch(biw[u].i)
6456 {
6457 case wSWORD:
6458 case wWSWORD:
6459 case wMSWORD:
6460 case wXSWORD:
6461 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6462 break;
6463
6464 case wSWORDSLASH:
6465 case wWSWORDSLASH:
6466 case wMSWORDSLASH:
6467 case wXSWORDSLASH:
6468 m=4;
6469 break;
6470
6471 case iwMMeter:
6472 m=9;
6473 break;
6474
6475 case wBRANG:
6476 case wMBRANG:
6477 case wFBRANG:
6478 m=BSZ2?1:3;
6479 break;
6480
6481 case wBOOM:
6482 case wSBOOM:
6483 case ewBOOM:
6484 case ewSBOOM:
6485 ignore_frames=true;
6486 m=2;
6487 break;
6488
6489 case wWAND:
6490 m=1;
6491 break;
6492
6493 case wMAGIC:
6494 m=1;
6495 break;
6496
6497 case wARROW:
6498 case wSARROW:
6499 case wGARROW:
6500 case ewARROW:
6501 m=1;
6502 break;
6503
6504 case wHAMMER:
6505 m=8;
6506 break;
6507
6508 case wHSHEAD:
6509 m=1;
6510 break;
6511
6512 case wHSCHAIN_H:
6513 m=1;
6514 break;
6515
6516 case wHSCHAIN_V:
6517 m=1;
6518 break;
6519
6520 case wHSHANDLE:
6521 m=1;
6522 break;
6523
6524 case iwDeath:
6525 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6526 {
6527 ignore_frames = true;
6528 m=BSZ2?4:2;
6529 }
6530 break;
6531
6532 case iwSpawn:
6533 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6534 {
6535 ignore_frames = true;
6536 m=3;
6537 }
6538 break;
6539 }
6540
6541 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6542 1, fmt::format("{} {}", biw[u].s, id));
6543
6544 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6545 //...these can't be updated by a move.
6546 if((u==3)||(u==9))
6547 {
6548 static int32_t impact_tiles[2] = {54,54};
6549 auto& tile = impact_tiles[u==3 ? 0 : 1];
6550 tile = 54; //dummy tile, ensure it's correct
6551 movelist->add_tile(&tile, 2, 1,
6552 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6553 true);
6554 }
6555 }
6556 if(!every_proc && !movelist->check_prot())
6557 return false;
6558 }
6559 //Hero sprites
6560 {
6561 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6562 dest_process, source_process, mode,
6563 move
6564 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6565 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6566 ));
6567 {
6568 int32_t a_style=(zinit.heroAnimationStyle);
6569 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6570 do \
6571 { \
6572 movelist->add_tile(&ref_sprite[spr_tile], \
6573 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6574 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6575 name, false, \
6576 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6577 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6578 } while(false)
6579 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6580
6581 for(int32_t i=0; i<4; ++i)
6582 {
6583 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6584 }
6585
6586 for(int32_t i=0; i<4; ++i)
6587 {
6588 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6589 }
6590
6591 for(int32_t i=0; i<4; ++i)
6592 {
6593 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6594 }
6595
6596 for(int32_t i=0; i<4; ++i)
6597 {
6598 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6599 }
6600
6601 for(int32_t i=0; i<2; ++i)
6602 {
6603 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6604 }
6605
6606 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6607
6608 for(int32_t i=0; i<4; ++i)
6609 {
6610 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6611 }
6612
6613 for(int32_t i=0; i<4; ++i)
6614 {
6615 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6616 }
6617
6618 for(int32_t i=0; i<4; ++i)
6619 {
6620 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6621 }
6622
6623 for(int32_t i=0; i<2; ++i)
6624 {
6625 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6626 }
6627
6628 for(int32_t i=0; i<4; ++i)
6629 {
6630 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6631 }
6632
6633 for(int32_t i=0; i<4; ++i)
6634 {
6635 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6636 }
6637 for(int32_t i=0; i<4; ++i)
6638 {
6639 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6640 }
6641 for(int32_t i=0; i<4; ++i)
6642 {
6643 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6644 }
6645 for(int32_t i=0; i<4; ++i)
6646 {
6647 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6648 }
6649 for(int32_t i=0; i<4; ++i)
6650 {
6651 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6652 }
6653 for(int32_t i=0; i<4; ++i)
6654 {
6655 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6656 }
6657 for(int32_t i=0; i<4; ++i)
6658 {
6659 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6660 }
6661 for(int32_t i=0; i<4; ++i)
6662 {
6663 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6664 }
6665 //69
6666 for(int32_t i=0; i<4; ++i)
6667 {
6668 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6669 }
6670 //73
6671 for(int32_t i=0; i<4; ++i)
6672 {
6673 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6674 }
6675 //77
6676 for(int32_t i=0; i<4; ++i)
6677 {
6678 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6679 }
6680 //81
6681 for(int32_t i=0; i<4; ++i)
6682 {
6683 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6684 }
6685 //85
6686 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6687 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6688 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6689 for(int32_t i=0; i<4; ++i)
6690 {
6691 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6692 }
6693 //91
6694 }
6695 if(!every_proc && !movelist->check_prot())
6696 return false;
6697 }
6698 //Map Styles
6699 {
6700 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6701 dest_process, source_process, mode,
6702 move
6703 ? "The tiles used by the following map styles will be partially cleared by the move."
6704 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6705 ));
6706 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6707 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6708 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6709 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6710 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6711 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6712 if(!every_proc && !movelist->check_prot())
6713 return false;
6714 }
6715 //Game Icons
6716 {
6717 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6718 dest_process, source_process, mode,
6719 move
6720 ? "The tiles used by the following game icons will be partially cleared by the move."
6721 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6722 ));
6723 for(int32_t u=0; u<4; u++)
6724 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6725 if(!every_proc && !movelist->check_prot())
6726 return false;
6727 }
6728 //DMaps
6729 {
6730 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6731 dest_process, source_process, mode,
6732 move
6733 ? "The tiles used by the following dmaps will be partially cleared by the move."
6734 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6735 ));
6736 for(int32_t u=0; u<MAXDMAPS; u++)
6737 {
6738 auto& dm = DMaps[u];
6739 movelist->add_tile(&dm.minimap_tile[0], 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6740 movelist->add_tile(&dm.minimap_tile[1], 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6741 movelist->add_tile(&dm.largemap_tile[0], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6742 movelist->add_tile(&dm.largemap_tile[1], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6743 }
6744 if(!every_proc && !movelist->check_prot())
6745 return false;
6746 }
6747 //Enemies
6748 {
6749 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6750 dest_process, source_process, mode,
6751 move
6752 ? "The tiles used by the following enemies will be partially cleared by the move."
6753 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6754 ));
6755 build_bie_list(false);
6756 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6757 for(int u=0; u<eMAXGUYS; u++)
6758 {
6759 guydata& enemy=guysbuf[bie[u].i];
6760 bool darknut=false;
6761 bool gleeok=false;
6762
6763 if(enemy.type==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6764 darknut=true;
6765 else if(enemy.type==eeGLEEOK)
6766 gleeok=true;
6767 else if (enemy.type == eePATRA)
6768 {
6769 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6770 {
6771 darknut=true; //uses the same logic no need for separate variables!
6772 }
6773 }
6774
6775 // Dummied out enemies
6776 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6777 {
6778 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6779 {
6780 continue;
6781 }
6782 }
6783
6784 if(newtiles)
6785 {
6786 if(enemy.e_tile==0)
6787 {
6788 continue;
6789 }
6790
6791 vector<std::tuple<int,int,int>> rects;
6792
6793 if(darknut) //or anything that uses S. Tile for with new tiles
6794 {
6795 if (enemy.s_tile != 0)
6796 {
6797 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6798 }
6799 }
6800 else if (gleeok)
6801 {
6802 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6803 {
6804 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6805 }
6806 rects.emplace_back(enemy.attributes[7], 4, 1);
6807 rects.emplace_back(enemy.attributes[8], 4, 1);
6808 }
6809 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6810 false, 0, 0, rects);
6811
6812 }
6813 else
6814 {
6815 if(enemy.tile==0)
6816 {
6817 continue;
6818 }
6819 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6820
6821 if(enemy.s_tile!=0)
6822 {
6823 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6824 }
6825 }
6826 }
6827 if(!every_proc && !movelist->check_prot())
6828 return false;
6829 }
6830 //Subscreens
6831 {
6832 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6833 dest_process, source_process, mode,
6834 move
6835 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6836 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6837 ));
6838
6839 for(auto q = 0; q < subscreens_active.size(); ++q)
6840 {
6841 size_t indx = movelist->move_refs.size();
6842 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6843 for(; indx < movelist->move_refs.size(); ++indx)
6844 {
6845 auto& ref = movelist->move_refs[indx];
6846 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6847 }
6848 }
6849 for(auto q = 0; q < subscreens_passive.size(); ++q)
6850 {
6851 size_t indx = movelist->move_refs.size();
6852 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6853 for(; indx < movelist->move_refs.size(); ++indx)
6854 {
6855 auto& ref = movelist->move_refs[indx];
6856 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6857 }
6858 }
6859 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6860 {
6861 size_t indx = movelist->move_refs.size();
6862 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6863 for(; indx < movelist->move_refs.size(); ++indx)
6864 {
6865 auto& ref = movelist->move_refs[indx];
6866 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6867 }
6868 }
6869 for(auto q = 0; q < subscreens_map.size(); ++q)
6870 {
6871 size_t indx = movelist->move_refs.size();
6872 collect_subscreen_tiles(subscreens_map[q], *movelist.get());
6873 for(; indx < movelist->move_refs.size(); ++indx)
6874 {
6875 auto& ref = movelist->move_refs[indx];
6876 ref->name = fmt::format("Map Subscr {} - {}", q, ref->name);
6877 }
6878 }
6879 if(!every_proc && !movelist->check_prot())
6880 return false;
6881 }
6882 //Strings
6883 {
6884 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6885 dest_process, source_process, mode,
6886 move
6887 ? "The tiles used by the following strings will be partially cleared by the move."
6888 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6889 ));
6890 for(size_t q = 0; q < msg_count; ++q)
6891 {
6892 MsgStr& str = MsgStrings[q];
6893 std::string text = str.serialize();
6894 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6895 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6896 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(text,100)));
6897 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6898 fmt::format("{} (Port.): '{}'", q, util::snip(text,100)));
6899 }
6900 if(!every_proc && !movelist->check_prot())
6901 return false;
6902 }
6903
6904 if(source_process) //Apply the 'diff' value to all moved tiles
6905 storage.redo();
6906 if(every_proc)
6907 for(auto &list : vec)
6908 for(auto &ref : list->move_refs)
6909 ref->forEach(every_proc);
6910 return true;
6911 }
6912 bool handle_tile_move(TileMoveProcess dest_process)
6913 {
6914 return _handle_tile_move(dest_process, nullopt, 0);
6915 }
6916 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6917 {
6918 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6919 }
6920 void for_every_used_tile(std::function<void(int32_t)> proc)
6921 {
6922 reset_combo_animations();
6923 reset_combo_animations2();
6924 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6925 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6926 }
6927
6928 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6929 {
6930 bool move = source_process.has_value();
6931 ComboMoveUndo local_undo;
6932 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6933 auto& vec = storage.vec;
6934 auto& combo_links = storage.combo_links;
6935 storage.diff = diff;
6936 storage.state = false;
6937 //Combo relative links
6938 {
6939 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6940 {
6941 newcombo& cmb = combobuf[q];
6942 for(size_t idx = 0; idx < cmb.triggers.size(); ++idx)
6943 {
6944 auto& trig = cmb.triggers[idx];
6945 if(trig.trigchange)
6946 combo_links.add_to(q, q+trig.trigchange);
6947 }
6948 bool next = cmb.flag == mfSECRETSNEXT;
6949 switch(cmb.type)
6950 {
6951 case cPOUND:
6952 case cLOCKBLOCK: case cLOCKBLOCK2:
6953 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
6954 case cCHEST: case cCHEST2:
6955 case cLOCKEDCHEST: case cLOCKEDCHEST2:
6956 case cBOSSCHEST: case cBOSSCHEST2:
6957 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
6958 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
6959 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
6960 case cTALLGRASSNEXT: case cCRUMBLE:
6961 next = true;
6962 break;
6963 case cCSWITCH: case cCSWITCHBLOCK:
6964 combo_links.add_to(q, q+cmb.attributes[0]);
6965 break;
6966 case cLIGHTTARGET:
6967 if(cmb.usrflags & cflag1)
6968 combo_links.add_to(q, q-1);
6969 else next = true;
6970 break;
6971 case cSTEPSFX:
6972 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
6973 next = true;
6974 break;
6975 }
6976 if(next)
6977 combo_links.add_to(q, q+1);
6978 }
6979 }
6980
6981 //This function is expensive! Any optimizations possible should be made. -Em
6982
6983 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
6984 #define ADDC(ptr, str) \
6985 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
6986 #define ADDC_10k(ptr, str) \
6987 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
6988 //Combos
6989 {
6990 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
6991 combo_links, dest_process, source_process,
6992 move
6993 ? "The combos used by the following combos will be partially cleared by the move."
6994 : "The combos used by the following combos will be partially or completely overwritten by this process."
6995 ));
6996 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6997 {
6998 newcombo& cmb = combobuf[q];
6999 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7000 : fmt::format(" ({})", cmb.label));
7001 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7002 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7003 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7004 for(auto& trig : cmb.triggers)
7005 ADDC(&trig.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7006
7007 //type-specific
7008 char const* type_name = ZI.getComboTypeName(cmb.type);
7009 switch(cmb.type)
7010 {
7011 case cLOCKEDCHEST: case cBOSSCHEST:
7012 if(cmb.usrflags & cflag13)
7013 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7014 [[fallthrough]];
7015 case cCHEST:
7016 if(cmb.usrflags & cflag13)
7017 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7018 break;
7019 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7020 if(cmb.usrflags & cflag13)
7021 {
7022 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7023 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7024 }
7025 break;
7026 case cSIGNPOST:
7027 if(cmb.usrflags & cflag13)
7028 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7029 break;
7030 case cBUTTONPROMPT:
7031 if(cmb.usrflags & cflag13)
7032 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7033 break;
7034 }
7035 }
7036
7037 if(!movelist->check_prot())
7038 return false;
7039 }
7040 //Door Combo Sets
7041 {
7042 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7043 combo_links, dest_process, source_process,
7044 move
7045 ? "The combos used by the following screens will be partially cleared by the move."
7046 : "The combos used by the following screens will be partially or completely overwritten by this process."
7047 ));
7048 static const char* door_names[9] = {
7049 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7050 };
7051 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7052 {
7053 auto& dcs = DoorComboSets[i];
7054 auto& name = DoorComboSetNames[i];
7055 for(int32_t j=0; j<9; j++)
7056 {
7057 if(j<4)
7058 {
7059 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7060
7061 if(j<3)
7062 {
7063 if(j<2)
7064 {
7065 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7066 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7067 }
7068 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7069 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7070 }
7071 }
7072
7073 for(int32_t k=0; k<6; k++)
7074 {
7075 if(k<4)
7076 {
7077 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7078 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7079 }
7080
7081 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7082 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7083 }
7084 }
7085 }
7086
7087 if(!movelist->check_prot())
7088 return false;
7089 }
7090 //Combo Pools
7091 {
7092 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7093 combo_links, dest_process, source_process,
7094 move
7095 ? "The combos used by the following combo pools will be partially cleared by the move."
7096 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7097 ));
7098 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7099 {
7100 combo_pool& pool = combo_pools[q];
7101 int idx = 0;
7102 for(cpool_entry& cp : pool.combos)
7103 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7104 }
7105
7106 if(!movelist->check_prot())
7107 return false;
7108 }
7109 //Auto Combos
7110 {
7111 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7112 combo_links, dest_process, source_process,
7113 move
7114 ? "The combos used by the following autocombos will be partially cleared by the move."
7115 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7116 ));
7117 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7118 {
7119 combo_auto& cauto = combo_autos[q];
7120 int idx = 0;
7121 for (autocombo_entry& ac : cauto.combos)
7122 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7123 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7124 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7125 }
7126
7127 if(!movelist->check_prot())
7128 return false;
7129 }
7130 //Combo Aliases
7131 {
7132 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7133 combo_links, dest_process, source_process,
7134 move
7135 ? "The combos used by the following aliases will be partially cleared by the move."
7136 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7137 ));
7138 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7139 {
7140 //dimensions are 1 less than you would expect -DD
7141 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7142
7143 for(int32_t j=0; j<count; j++)
7144 {
7145 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7146 }
7147 }
7148
7149 if(!movelist->check_prot())
7150 return false;
7151 }
7152 //Favorite Combos
7153 {
7154 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7155 combo_links, dest_process, source_process,
7156 move
7157 ? "The combos used by the following favorite combos will be partially cleared by the move."
7158 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7159 ));
7160 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7161 {
7162 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7163 continue;
7164 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7165 }
7166
7167 if(!movelist->check_prot())
7168 return false;
7169 }
7170 //Bottle Shops
7171 {
7172 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7173 combo_links, dest_process, source_process,
7174 move
7175 ? "The combos used by the following bottle shops will be partially cleared by the move."
7176 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7177 ));
7178 for(auto q = 0; q < 256; ++q)
7179 for(auto p = 0; p < 3; ++p)
7180 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7181
7182 if(!movelist->check_prot())
7183 return false;
7184 }
7185 //Screens //EXPENSIVE! DO THIS LAST!
7186 {
7187 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7188 combo_links, dest_process, source_process,
7189 move
7190 ? "The combos used by the following screens will be partially cleared by the move."
7191 : "The combos used by the following screens will be partially or completely overwritten by this process."
7192 ));
7193
7194 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7195 {
7196 for(int32_t j=0; j<MAPSCRS; j++)
7197 {
7198 mapscr& scr = TheMaps[i*MAPSCRS+j];
7199
7200 if(!(scr.valid&mVALID))
7201 continue;
7202
7203 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7204
7205 // Specifying the exact position is too expensive - too much string creation.
7206 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7207 for(int32_t k=0; k<176; k++)
7208 ADDC(&scr.data[k], data_str);
7209
7210 for(int32_t k=0; k<128; k++)
7211 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7212
7213 word maxffc = scr.numFFC();
7214 for(word k=0; k<maxffc; k++)
7215 {
7216 ffcdata& ffc = scr.ffcs[k];
7217 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7218 }
7219 }
7220 }
7221
7222 if(!movelist->check_prot())
7223 return false;
7224 }
7225 if(source_process) //Apply the 'diff' value to all moved combos
7226 storage.redo();
7227 return true;
7228 }
7229
7230 bool handle_combo_move(ComboMoveProcess dest_process)
7231 {
7232 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7233 }
7234 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7235 {
7236 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7237 }
7238 void register_used_tiles()
7239 {
7240 memset(used_tile_table, 0, sizeof(used_tile_table));
7241 for_every_used_tile([&](int tile)
7242 {
7243 used_tile_table[tile] = true;
7244 });
7245 }
7246
7247 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7248 {
7249 bool ctrl=(CHECK_CTRL_CMD);
7250 bool copied=false;
7251 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7252
7253 if(copied)
7254 {
7255 mark_save_dirty();
7256 }
7257
7258 return copied;
7259 }
7260
7261 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7262 {
7263 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7264 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7265
7266 // if tile>tile2 then swap them
7267 if(tile>tile2)
7268 {
7269 zc_swap(tile, tile2);
7270 }
7271
7272 // alt=copy from right
7273 // shift=copy from bottom
7274
7275 int32_t copies=copycnt;
7276 int32_t dest_first=tile;
7277 int32_t dest_last=tile2;
7278 int32_t src_first=copy;
7279 int32_t src_last=copy+copies-1;
7280
7281 int32_t dest_top=0;
7282 int32_t dest_bottom=0;
7283 int32_t src_top=0;
7284 int32_t src_bottom=0;
7285 int32_t src_left=0, src_right=0;
7286 int32_t src_width=0, src_height=0;
7287 int32_t dest_left=0, dest_right=0;
7288 int32_t dest_width=0, dest_height=0;
7289 int32_t rows=0, cols=0;
7290
7291 if(rect)
7292 {
7293 dest_top=TILEROW(dest_first);
7294 dest_bottom=TILEROW(dest_last);
7295 src_top=TILEROW(src_first);
7296 src_bottom=TILEROW(src_last);
7297
7298 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7299 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7300 src_first=(src_top * TILES_PER_ROW)+src_left;
7301 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7302
7303 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7304 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7305 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7306 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7307
7308 //if no dest range set, then set one
7309 if((dest_first==dest_last)&&(src_first!=src_last))
7310 {
7311 if(alt)
7312 {
7313 dest_left=dest_right-(src_right-src_left);
7314 }
7315 else
7316 {
7317 dest_right=dest_left+(src_right-src_left);
7318 }
7319
7320 if(shift)
7321 {
7322 dest_top=dest_bottom-(src_bottom-src_top);
7323 }
7324 else
7325 {
7326 dest_bottom=dest_top+(src_bottom-src_top);
7327 }
7328
7329 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7330 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7331 }
7332 else
7333 {
7334 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7335 {
7336 if(alt) //copy from right tile instead of left
7337 {
7338 src_left=src_right-(dest_right-dest_left);
7339 }
7340 else //copy from left tile
7341 {
7342 src_right=src_left+(dest_right-dest_left);
7343 }
7344 }
7345 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7346 {
7347 if(alt) //copy from right tile instead of left
7348 {
7349 dest_left=dest_right-(src_right-src_left);
7350 }
7351 else //copy from left tile
7352 {
7353 dest_right=dest_left+(src_right-src_left);
7354 }
7355 }
7356
7357 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7358 {
7359 if(shift) //copy from bottom tile instead of top
7360 {
7361 src_top=src_bottom-(dest_bottom-dest_top);
7362 }
7363 else //copy from top tile
7364 {
7365 src_bottom=src_top+(dest_bottom-dest_top);
7366 }
7367 }
7368 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7369 {
7370 if(shift) //copy from bottom tile instead of top
7371 {
7372 dest_top=dest_bottom-(src_bottom-src_top);
7373 }
7374 else //copy from top tile
7375 {
7376 dest_bottom=dest_top+(src_bottom-src_top);
7377 }
7378 }
7379
7380 src_first=(src_top * TILES_PER_ROW)+src_left;
7381 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7382 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7383 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7384 }
7385
7386 cols=src_right-src_left+1;
7387 rows=src_bottom-src_top+1;
7388
7389 dest_width=dest_right-dest_left+1;
7390 dest_height=dest_bottom-dest_top+1;
7391 src_width=src_right-src_left+1;
7392 src_height=src_bottom-src_top+1;
7393
7394 }
7395 else //!rect
7396 {
7397 //if no dest range set, then set one
7398 if((dest_first==dest_last)&&(src_first!=src_last))
7399 {
7400 if(alt)
7401 {
7402 dest_first=dest_last-(src_last-src_first);
7403 }
7404 else
7405 {
7406 dest_last=dest_first+(src_last-src_first);
7407 }
7408 }
7409 else
7410 {
7411 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7412 {
7413 if(alt) //copy from last tile instead of first
7414 {
7415 src_first=src_last-(dest_last-dest_first);
7416 }
7417 else //copy from first tile
7418 {
7419 src_last=src_first+(dest_last-dest_first);
7420 }
7421 }
7422 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7423 {
7424 if(alt) //copy from last tile instead of first
7425 {
7426 dest_first=dest_last-(src_last-src_first);
7427 }
7428 else //copy from first tile
7429 {
7430 dest_last=dest_first+(src_last-src_first);
7431 }
7432 }
7433 }
7434
7435 copies=dest_last-dest_first+1;
7436 }
7437
7438
7439
7440 char buf2[80], buf3[80], buf4[80];
7441 sprintf(buf2, " ");
7442 sprintf(buf3, " ");
7443 sprintf(buf4, " ");
7444
7445 // warn if range extends beyond last tile
7446 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7447
7448 if(dest_last>=NEWMAXTILES)
7449 {
7450 displayinfo("Destination Error", fmt::format("The destination extends beyond the last available tile row. {} operation cancelled.", move ? "Move" : "Copy"));
7451 return false;
7452 }
7453
7454
7455 TileMoveUndo on_undo;
7456 // Overwrite warnings
7457 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7458 if(move)
7459 {
7460 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7461 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7462 return false;
7463 }
7464 else
7465 {
7466 if(!handle_tile_move(dest))
7467 return false;
7468 }
7469 // copy tiles and delete if needed (move)
7470
7471 {
7472 go_tiles();
7473
7474 int32_t diff=dest_first-src_first;
7475
7476 if(rect)
7477 {
7478 for(int32_t r=0; r<rows; ++r)
7479 {
7480 for(int32_t c=0; c<cols; ++c)
7481 {
7482 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7483 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7484
7485 if(dt>=NEWMAXTILES)
7486 continue;
7487
7488 overlay_tile(newtilebuf,dt,st,cs,backwards);
7489
7490 }
7491 }
7492 }
7493 else
7494 {
7495 for(int32_t c=0; c<copies; ++c)
7496 {
7497 int32_t dt=(dest_first+c);
7498 int32_t st=(src_first+c);
7499
7500 if(dt>=NEWMAXTILES)
7501 continue;
7502
7503 overlay_tile(newtilebuf,dt,st,cs,backwards);
7504
7505 if(move)
7506 {
7507 if(st<dest_first||st>(dest_first+c-1))
7508 reset_tile(newtilebuf, st, tf4Bit);
7509 }
7510 }
7511 }
7512 }
7513
7514 //now that tiles have moved, fix these buffers -DD
7515 register_blank_tiles();
7516 register_used_tiles();
7517
7518 if(move)
7519 last_tile_move_list = std::move(on_undo);
7520 return true;
7521 }
7522 //
7523 bool do_movetile_united(tile_move_data const& tmd)
7524 {
7525 char buf2[80], buf3[80], buf4[80];
7526 sprintf(buf2, " ");
7527 sprintf(buf3, " ");
7528 sprintf(buf4, " ");
7529
7530 // warn if range extends beyond last tile
7531 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7532
7533 if(tmd.dest_last>=NEWMAXTILES)
7534 {
7535 displayinfo("Destination Error", fmt::format("The destination extends beyond the last available tile row. {} operation cancelled.", tmd.move ? "Move" : "Copy"));
7536 return false;
7537 }
7538
7539 TileMoveUndo on_undo;
7540 // Overwrite warnings
7541 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7542 if(tmd.move)
7543 {
7544 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7545 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7546 return false;
7547 }
7548 else
7549 {
7550 if(!handle_tile_move(dest))
7551 return false;
7552 }
7553
7554 // copy tiles and delete if needed (tmd.move)
7555 {
7556 go_tiles();
7557
7558 if(tmd.rect)
7559 {
7560 for(int32_t r=0; r<tmd.rows; ++r)
7561 {
7562 for(int32_t c=0; c<tmd.cols; ++c)
7563 {
7564 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7565 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7566
7567 if(dt>=NEWMAXTILES)
7568 continue;
7569
7570 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7571
7572 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7573 {
7574 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7575 }
7576
7577 if(tmd.move)
7578 {
7579 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7580 reset_tile(newtilebuf, st, tf4Bit);
7581 else
7582 {
7583 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7584 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7585 if(destLeft<=destRight)
7586 {
7587 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7588 reset_tile(newtilebuf, st, tf4Bit);
7589 }
7590 else // Wrapped around
7591 {
7592 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7593 reset_tile(newtilebuf, st, tf4Bit);
7594 }
7595 }
7596 }
7597 }
7598 }
7599 }
7600 else
7601 {
7602 for(int32_t c=0; c<tmd.copies; ++c)
7603 {
7604 int32_t dt=(tmd.dest_first+c);
7605 int32_t st=(tmd.src_first+c);
7606
7607 if(dt>=NEWMAXTILES)
7608 continue;
7609
7610 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7611
7612 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7613 {
7614 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7615 }
7616
7617 if(tmd.move)
7618 {
7619 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7620 reset_tile(newtilebuf, st, tf4Bit);
7621 }
7622 }
7623 }
7624 }
7625
7626 //now that tiles have moved, fix these buffers -DD
7627 register_blank_tiles();
7628 register_used_tiles();
7629
7630 if(tmd.move)
7631 last_tile_move_list = std::move(on_undo);
7632 return true;
7633 }
7634
7635 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7636 {
7637 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7638 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7639
7640 // if tile>tile2 then swap them
7641 if(tile>tile2)
7642 {
7643 zc_swap(tile, tile2);
7644 }
7645
7646 // alt=copy from right
7647 // shift=copy from bottom
7648 tile_move_data tmd;
7649
7650 tmd.copies=copycnt;
7651 tmd.dest_first=tile;
7652 tmd.dest_last=tile2;
7653 tmd.src_first=copy;
7654 tmd.src_last=copy+tmd.copies-1;
7655 tmd.rect = rect;
7656 tmd.move = move;
7657
7658 if(rect)
7659 {
7660 tmd.dest_top=TILEROW(tmd.dest_first);
7661 tmd.dest_bottom=TILEROW(tmd.dest_last);
7662 tmd.src_top=TILEROW(tmd.src_first);
7663 tmd.src_bottom=TILEROW(tmd.src_last);
7664
7665 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7666 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7667 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7668 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7669
7670 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7671 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7672 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7673 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7674
7675 //if no dest range set, then set one
7676 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7677 {
7678 if(alt)
7679 {
7680 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7681 }
7682 else
7683 {
7684 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7685 }
7686
7687 if(shift)
7688 {
7689 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7690 }
7691 else
7692 {
7693 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7694 }
7695
7696 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7697 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7698 }
7699 else
7700 {
7701 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7702 {
7703 if(alt) //copy from right tile instead of left
7704 {
7705 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7706 }
7707 else //copy from left tile
7708 {
7709 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7710 }
7711 }
7712 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7713 {
7714 if(alt) //copy from right tile instead of left
7715 {
7716 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7717 }
7718 else //copy from left tile
7719 {
7720 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7721 }
7722 }
7723
7724 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7725 {
7726 if(shift) //copy from bottom tile instead of top
7727 {
7728 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7729 }
7730 else //copy from top tile
7731 {
7732 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7733 }
7734 }
7735 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7736 {
7737 if(shift) //copy from bottom tile instead of top
7738 {
7739 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7740 }
7741 else //copy from top tile
7742 {
7743 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7744 }
7745 }
7746
7747 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7748 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7749 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7750 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7751 }
7752
7753 tmd.cols=tmd.src_right-tmd.src_left+1;
7754 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7755
7756 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7757 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7758 tmd.src_width=tmd.src_right-tmd.src_left+1;
7759 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7760
7761 }
7762 else //!rect
7763 {
7764 //if no dest range set, then set one
7765 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7766 {
7767 if(alt)
7768 {
7769 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7770 }
7771 else
7772 {
7773 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7774 }
7775 }
7776 else
7777 {
7778 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7779 {
7780 if(alt) //copy from last tile instead of first
7781 {
7782 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7783 }
7784 else //copy from first tile
7785 {
7786 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7787 }
7788 }
7789 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7790 {
7791 if(alt) //copy from last tile instead of first
7792 {
7793 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7794 }
7795 else //copy from first tile
7796 {
7797 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7798 }
7799 }
7800 }
7801
7802 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7803 }
7804
7805 return do_movetile_united(tmd);
7806 }
7807
7808 //
7809
7810 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7811 {
7812 assert(!move); //not implemented
7813
7814 // if tile>tile2 then swap them
7815 if(tile>tile2)
7816 {
7817 zc_swap(tile, tile2);
7818 }
7819
7820 tile_move_data tmd;
7821 tmd.copies=copycnt;
7822 tmd.dest_first=tile;
7823 tmd.dest_last=tile2;
7824 tmd.src_first=copy;
7825 tmd.src_last=copy+tmd.copies-1;
7826
7827
7828
7829 if(rect)
7830 {
7831 tmd.dest_top=TILEROW(tmd.dest_first);
7832 tmd.dest_bottom=TILEROW(tmd.dest_last);
7833 //tmd.src_top=TILEROW(tmd.src_first);
7834 //tmd.src_bottom=TILEROW(tmd.src_last);
7835
7836 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7837 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7838 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7839 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7840
7841 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7842 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7843 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7844 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7845
7846
7847
7848
7849 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7850 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7851
7852 tmd.cols=tmd.dest_width+1;
7853 tmd.rows=tmd.dest_height+1;
7854
7855 al_trace("tmd.rows: %d\n", tmd.rows);
7856 al_trace("tmd.cols: %d\n", tmd.cols);
7857
7858
7859 }
7860 else //!rect
7861 {
7862 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7863 }
7864
7865
7866
7867 char buf2[80], buf3[80], buf4[80];
7868 sprintf(buf2, " ");
7869 sprintf(buf3, " ");
7870 sprintf(buf4, " ");
7871
7872 // warn if range extends beyond last tile
7873 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7874
7875 if(tmd.dest_last>=NEWMAXTILES)
7876 {
7877 displayinfo("Destination Error", fmt::format("The destination extends beyond the last available tile row. {} operation cancelled.", move ? "Move" : "Copy"));
7878 return false;
7879 }
7880
7881 TileMoveUndo on_undo;
7882 // Overwrite warnings
7883 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7884 if(tmd.move)
7885 {
7886 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7887 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7888 return false;
7889 }
7890 else
7891 {
7892 if(!handle_tile_move(dest))
7893 return false;
7894 }
7895
7896 // copy tiles and delete if needed (move)
7897
7898 {
7899 go_tiles();
7900
7901 int32_t diff=tmd.dest_first-tmd.src_first;
7902
7903 if(rect)
7904 {
7905 al_trace("floodfill, rect\n");
7906 al_trace("tmd.rows: %d\n", tmd.rows);
7907 al_trace("tmd.cols: %d\n", tmd.cols);
7908 for(int32_t r=0; r<tmd.rows; ++r)
7909 {
7910 for(int32_t c=0; c<tmd.cols; ++c)
7911 {
7912 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7913 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7914
7915 if(dt>=NEWMAXTILES)
7916 continue;
7917
7918 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7919
7920 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7921 {
7922 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7923 }
7924 }
7925 }
7926 }
7927 else
7928 {
7929 for(int32_t c=0; c<tmd.copies; ++c)
7930 {
7931 int32_t dt=(tmd.dest_first+c);
7932 int32_t st=(tmd.src_first+c);
7933
7934 if(dt>=NEWMAXTILES)
7935 continue;
7936
7937 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7938
7939 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7940 {
7941 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7942 }
7943
7944 }
7945 }
7946 }
7947
7948 //now that tiles have moved, fix these buffers -DD
7949 register_blank_tiles();
7950 register_used_tiles();
7951
7952 if(tmd.move)
7953 last_tile_move_list = std::move(on_undo);
7954 return true;
7955 }
7956 //
7957
7958 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7959 {
7960 al_trace("Floodfill Psste\n");
7961 bool ctrl=(CHECK_CTRL_CMD);
7962 bool copied=false;
7963 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
7964
7965 if(copied)
7966 {
7967 if(!ctrl)
7968 {
7969 copy=-1;
7970 tile2=tile;
7971 }
7972
7973 mark_save_dirty();
7974 }
7975
7976 return copied;
7977 }
7978
7979 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7980 {
7981 bool ctrl=(CHECK_CTRL_CMD);
7982 bool copied=false;
7983 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
7984
7985 if(copied)
7986 {
7987 if(!ctrl)
7988 {
7989 copy=-1;
7990 tile2=tile;
7991 }
7992
7993 mark_save_dirty();
7994 }
7995
7996 return copied;
7997 }
7998
7999 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8000 {
8001 // if tile>tile2 then swap them
8002 if(tile>tile2)
8003 {
8004 zc_swap(tile, tile2);
8005 }
8006 int32_t src_top = TILEROW(tile);
8007 int32_t src_bottom = TILEROW(tile2);
8008 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8009 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8010 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8011 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8012
8013 int32_t src_width = src_right-src_left+1,
8014 src_height = src_bottom-src_top+1;
8015 int32_t dest_width = src_width, dest_height = src_height;
8016 zfix dest_rot = 0_zf;
8017 if(rotate)
8018 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8019 else
8020 ScaleTileDialog(&dest_width, &dest_height).show();
8021 if (rotate)
8022 {
8023 if (dest_rot == 0) return false;
8024 }
8025 else
8026 {
8027 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8028 }
8029 dest_width = vbound(dest_width, 1, 20);
8030 dest_height = vbound(dest_height, 1, 20);
8031
8032 int32_t dest_top = src_top;
8033 int32_t dest_bottom = src_top+dest_height-1;
8034 int32_t dest_left = src_left;
8035 int32_t dest_right = src_left+dest_width-1;
8036 int32_t dest_first = src_first;
8037 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8038
8039
8040 if(dest_last>=NEWMAXTILES)
8041 {
8042 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8043 return false;
8044 }
8045
8046 // Overwrite warnings
8047 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8048 return false;
8049
8050 //Do the rotate
8051 {
8052 go_tiles();
8053
8054 int32_t diff=dest_first-src_first;
8055 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8056 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8057 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8058 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8059 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8060 if (rotate)
8061 {
8062 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8063 }
8064 else
8065 {
8066 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8067 0, 0, destbmp->w, destbmp->h);
8068 }
8069 int32_t mhei = zc_max(src_height,dest_height),
8070 mwid = zc_max(src_width, dest_width);
8071 for(int32_t r=0; r<mhei; ++r)
8072 {
8073 for(int32_t c=0; c<mwid; ++c)
8074 {
8075 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8076
8077 if(dt>=NEWMAXTILES)
8078 continue;
8079 if(r < dest_height && c < dest_width)
8080 {
8081 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8082 }
8083 else reset_tile(newtilebuf, dt, tf4Bit);
8084 }
8085 }
8086 }
8087
8088 register_blank_tiles();
8089 register_used_tiles();
8090 return true;
8091 }
8092
8093 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8094 {
8095 //these 2 shouldn't be needed, but just to be safe...
8096 reset_combo_animations();
8097 reset_combo_animations2();
8098
8099 if(tile2<tile)
8100 {
8101 zc_swap(tile,tile2);
8102 }
8103
8104 auto first = tile;
8105 auto last = masscopy ? tile2 : first + copycnt-1;
8106 if(!handle_combo_move({first,last}))
8107 return;
8108
8109 if(!masscopy)
8110 {
8111 if(tile==copy)
8112 {
8113 copy=-1;
8114 tile2=tile;
8115 return;
8116 }
8117
8118 // go_combos(); // commented because caller does it for us
8119 //if copying to an earlier combo, copy from left to right
8120 //otherwise, copy from right to left
8121 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8122 {
8123 if(tile+t < MAXCOMBOS)
8124 {
8125 combobuf[tile+t]=combobuf[copy+t];
8126 }
8127 }
8128
8129 copy=-1;
8130 tile2=tile;
8131 mark_save_dirty();
8132 }
8133 else
8134 {
8135 // go_combos();
8136 int32_t src=copy, dest=tile;
8137
8138 do
8139 {
8140 combobuf[dest]=combobuf[src];
8141 ++src;
8142 ++dest;
8143
8144 if((src-copy)==copycnt) src=copy;
8145 }
8146 while(dest<=tile2);
8147
8148 copy=-1;
8149 tile2=tile;
8150 mark_save_dirty();
8151 }
8152
8153 setup_combo_animations();
8154 setup_combo_animations2();
8155 }
8156
8157 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8158 {
8159 reset_combo_animations();
8160 reset_combo_animations2();
8161 go_combos();
8162
8163 auto diff = cmd.tile - cmd.copy1;
8164 if(is_undoing)
8165 on_undo.undo();
8166 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8167 return false;
8168
8169 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8170 {
8171 if(cmd.tile+t < MAXCOMBOS)
8172 {
8173 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8174 clear_combo(cmd.copy1+t);
8175 }
8176 }
8177
8178 setup_combo_animations();
8179 setup_combo_animations2();
8180 mark_save_dirty();
8181 return true;
8182 }
8183
8184 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8185 {
8186 if(tile2<tile)
8187 {
8188 zc_swap(tile,tile2);
8189 }
8190
8191 if(tile==copy)
8192 {
8193 copy=-1;
8194 tile2=tile;
8195 return;
8196 }
8197
8198 combo_move_data cmd;
8199 cmd.tile = tile;
8200 cmd.tile2 = tile2;
8201 cmd.copy1 = copy;
8202 cmd.copycnt = copycnt;
8203
8204 ComboMoveUndo on_undo;
8205 if(!do_movecombo(cmd, on_undo))
8206 return;
8207 last_combo_move_list = std::move(on_undo);
8208 copy=-1;
8209 tile2=tile;
8210 }
8211
8212 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8213 {
8214 if(firsttile > lasttile)
8215 zc_swap(firsttile,lasttile);
8216 int32_t coldiff = 0;
8217 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8218 {
8219 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8220 firsttile-=coldiff;
8221 lasttile+=coldiff;
8222 }
8223 for(int32_t t=firsttile; t<=lasttile; ++t)
8224 if(!rect_sel ||
8225 ((TILECOL(t)>=TILECOL(firsttile)) &&
8226 (TILECOL(t)<=TILECOL(lasttile))))
8227 reset_tile(newtilebuf, t, tf4Bit);
8228 mark_save_dirty();
8229 register_blank_tiles();
8230 }
8231
8232 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8233 {
8234 char buf[40];
8235
8236 if(tile==tile2)
8237 {
8238 sprintf(buf,"Delete tile %d?",tile);
8239 }
8240 else
8241 {
8242 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8243 }
8244
8245 if (alert_confirm("Confirm Delete",buf))
8246 {
8247 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8248
8249 go_tiles();
8250
8251 //if copying to an earlier tile, copy from left to right
8252 //otherwise, copy from right to left
8253 do_delete_tiles(firsttile, lasttile, rect_sel);
8254
8255 tile=tile2=zc_min(tile,tile2);
8256 mark_save_dirty();
8257 register_blank_tiles();
8258 }
8259 }
8260
8261 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8262 {
8263 byte buf[256];
8264 go_tiles();
8265
8266 unpack_tile(newtilebuf, dest, 0, false);
8267
8268 for(int32_t i=0; i<256; i++)
8269 buf[i] = unpackbuf[i];
8270
8271 unpack_tile(newtilebuf, src, 0, false);
8272
8273 if(newtilebuf[src].format>tf4Bit)
8274 {
8275 cs=0;
8276 }
8277
8278 cs &= 15;
8279 cs <<= CSET_SHFT;
8280
8281 for(int32_t i=0; i<256; i++)
8282 {
8283 if(backwards)
8284 {
8285 if(!buf[i])
8286 {
8287 buf[i] = unpackbuf[i]+cs;
8288 }
8289 }
8290 else
8291 {
8292 if(unpackbuf[i])
8293 {
8294 buf[i] = unpackbuf[i]+cs;
8295 }
8296 }
8297 }
8298
8299 pack_tile(newtilebuf, buf,dest);
8300 mark_save_dirty();
8301 }
8302
8303 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8304 {
8305 //byte buf[256];
8306 go_tiles();
8307
8308 if(!rect_sel)
8309 {
8310 for(int32_t d=dest1; d <= dest2; ++d)
8311 {
8312 /*unpack_tile(newtilebuf, d, 0, false);
8313
8314 for(int32_t i=0; i<256; i++)
8315 {
8316 if(!backwards)
8317 {
8318 if(!buf[i])
8319 {
8320 buf[i] = unpackbuf[i] + cs;
8321 }
8322 }
8323 else
8324 {
8325 if(unpackbuf[i])
8326 {
8327 buf[i] = unpackbuf[i] + cs;
8328 }
8329 }
8330 }
8331
8332 pack_tile(newtilebuf, buf,d);
8333 */
8334
8335 overlay_tile(newtilebuf,d,src,cs,backwards);
8336
8337 if(!blank_tile_table[src])
8338 {
8339 blank_tile_table[d]=false;
8340 }
8341 }
8342 }
8343 else
8344 {
8345 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8346 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8347 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8348 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8349 int32_t d=0;
8350
8351 for(int32_t j=cmin; j<=cmax; ++j)
8352 {
8353 for(int32_t k=rmin; k<=rmax; ++k)
8354 {
8355 d=j+TILES_PER_ROW*k;
8356 /*unpack_tile(newtilebuf, d, 0, false);
8357
8358 for(int32_t i=0; i<256; i++)
8359 {
8360 if(!backwards)
8361 {
8362 if(!buf[i])
8363 {
8364 buf[i] = unpackbuf[i] + cs;
8365 }
8366 }
8367 else
8368 {
8369 if(unpackbuf[i])
8370 {
8371 buf[i] = unpackbuf[i] + cs;
8372 }
8373 }
8374 }
8375
8376 pack_tile(newtilebuf, buf,d);
8377 */
8378
8379 overlay_tile(newtilebuf,d,src,cs,backwards);
8380
8381 if(!blank_tile_table[src])
8382 {
8383 blank_tile_table[d]=false;
8384 }
8385 }
8386 }
8387 }
8388
8389 return;
8390 }
8391
8392 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8393 {
8394 tile+=s;
8395 bound(tile,0,NEWMAXTILES-1);
8396
8397 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8398 tile2 = tile;
8399
8400 first = tile - (tile%TILES_PER_PAGE);
8401 }
8402
8403 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8404 {
8405 int32_t cst;
8406
8407 switch(bp2)
8408 {
8409 case tf4Bit:
8410 switch(newtilebuf[t].format)
8411 {
8412 case tf4Bit:
8413 //already in the right format
8414 break;
8415
8416 case tf8Bit:
8417 unpack_tile(newtilebuf, t, 0, true);
8418
8419 if(alt) //reduce
8420 {
8421 for(int32_t i=0; i<256; i++)
8422 {
8423 if(!shift||unpackbuf[i]!=0)
8424 {
8425 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8426 }
8427 }
8428 }
8429 else //truncate
8430 {
8431 for(int32_t i=0; i<256; i++)
8432 {
8433 unpackbuf[i]&=15;
8434 }
8435 }
8436
8437 reset_tile(newtilebuf, t, tf4Bit);
8438 pack_tile(newtilebuf, unpackbuf, t);
8439 break;
8440 }
8441
8442 break;
8443
8444 case tf8Bit:
8445 switch(newtilebuf[t].format)
8446 {
8447 case tf4Bit:
8448 unpack_tile(newtilebuf, t, 0, true);
8449 cst = cs&15;
8450 cst <<= CSET_SHFT;
8451
8452 for(int32_t i=0; i<256; i++)
8453 {
8454 if(!shift||unpackbuf[i]!=0)
8455 {
8456 unpackbuf[i]+=cst;
8457 }
8458 }
8459
8460 reset_tile(newtilebuf, t, tf8Bit);
8461 pack_tile(newtilebuf, unpackbuf, t);
8462 break;
8463
8464 case tf8Bit:
8465 //already in the right format
8466 break;
8467 }
8468
8469 break;
8470 }
8471 }
8472
8473 static DIALOG create_relational_tiles_dlg[] =
8474 {
8475 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8476 12 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8477 12 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8478 12 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8479 12 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8480 12 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8481 12 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8482 12 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8483 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8484 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8485 };
8486
8487 void draw_tile_list_window()
8488 {
8489 int32_t w = 640;
8490 int32_t h = 480;
8491
8492 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8493 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8494 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8495 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8496
8497 FONT *oldfont = font;
8498 font = get_zc_font(font_lfont);
8499 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8500 font=oldfont;
8501 return;
8502 }
8503
8504 void show_blank_tile(int32_t t)
8505 {
8506 displayinfo("Blank Tile Information",fmt::format(
8507 "Tile is{} blank.\n{} {}\n{} {}",
8508 blank_tile_table[t]?"":" not",
8509 blank_tile_quarters_table[t*4]?'X':'-',
8510 blank_tile_quarters_table[(t*4)+1]?'X':'-',
8511 blank_tile_quarters_table[(t*4)+2]?'X':'-',
8512 blank_tile_quarters_table[(t*4)+3]?'X':'-'));
8513 }
8514
8515 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8516 {
8517 int num_bits;
8518 if (format == tf4Bit)
8519 num_bits = 4;
8520 else if (format == tf8Bit)
8521 num_bits = 8;
8522 else assert(false);
8523
8524 char buf[80];
8525 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8526
8527 if (skip_prompt || alert_confirm("Convert Tile?",buf))
8528 {
8529 go_tiles();
8530 mark_save_dirty();
8531
8532 if(format == tf4Bit)
8533 {
8534 memset(cset_reduce_table, 0, 256);
8535 memset(col_diff,0,3*128);
8536 calc_cset_reduce_table(RAMpal, cs);
8537 }
8538
8539 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8540
8541 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8542 {
8543 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8544 firsttile-=coldiff;
8545 lasttile+=coldiff;
8546 }
8547
8548 for(int32_t t=firsttile; t<=lasttile; t++)
8549 if(!rect_sel ||
8550 ((TILECOL(t)>=TILECOL(firsttile)) &&
8551 (TILECOL(t)<=TILECOL(lasttile))))
8552 convert_tile(t, format, cs, shift, alt);
8553
8554 tile=tile2=zc_min(tile,tile2);
8555 }
8556 }
8557
8558
8559 int32_t readtilefile(PACKFILE *f)
8560 {
8561 dword section_version=0;
8562 int32_t zversion = 0;
8563 int32_t zbuild = 0;
8564
8565 if(!p_igetl(&zversion,f))
8566 {
8567 return 0;
8568 }
8569 if(!p_igetl(&zbuild,f))
8570 {
8571 return 0;
8572 }
8573 if(!p_igetw(&section_version,f))
8574 {
8575 return 0;
8576 }
8577 if(!read_deprecated_section_cversion(f))
8578 {
8579 return 0;
8580 }
8581 al_trace("readoneweapon section_version: %d\n", section_version);
8582
8583 if ( zversion > ZELDA_VERSION )
8584 {
8585 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8586 return 0;
8587 }
8588
8589 else if ( ( section_version > V_TILES ))
8590 {
8591 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8592 return 0;
8593
8594 }
8595 else
8596 {
8597 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8598 }
8599
8600 int32_t index = 0;
8601 int32_t count = 0;
8602
8603 //tile id
8604 if(!p_igetl(&index,f))
8605 {
8606 return 0;
8607 }
8608 al_trace("Reading tile: index(%d)\n", index);
8609
8610 //tile count
8611 if(!p_igetl(&count,f))
8612 {
8613 return 0;
8614 }
8615 al_trace("Reading tile: count(%d)\n", count);
8616
8617
8618
8619
8620 for ( int32_t tilect = 0; tilect < count; tilect++ )
8621 {
8622 byte *temp_tile = new byte[tilesize(tf32Bit)];
8623 byte format=tf4Bit;
8624 memset(temp_tile, 0, tilesize(tf32Bit));
8625 if(!p_getc(&format,f))
8626 {
8627 delete[] temp_tile;
8628 return 0;
8629 }
8630
8631
8632 if(!pfread(temp_tile,tilesize(format),f))
8633 {
8634 delete[] temp_tile;
8635 return 0;
8636 }
8637
8638 reset_tile(newtilebuf, index+(tilect), format);
8639 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8640 delete[] temp_tile;
8641 }
8642
8643
8644 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8645
8646 register_blank_tiles();
8647 register_used_tiles();
8648
8649 return 1;
8650
8651 }
8652
8653 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8654 {
8655 dword section_version=0;
8656 int32_t zversion = 0;
8657 int32_t zbuild = 0;
8658
8659 if(!p_igetl(&zversion,f))
8660 {
8661 return 0;
8662 }
8663 if(!p_igetl(&zbuild,f))
8664 {
8665 return 0;
8666 }
8667 if(!p_igetw(&section_version,f))
8668 {
8669 return 0;
8670 }
8671 if(!read_deprecated_section_cversion(f))
8672 {
8673 return 0;
8674 }
8675 al_trace("readoneweapon section_version: %d\n", section_version);
8676
8677 if ( zversion > ZELDA_VERSION )
8678 {
8679 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8680 return 0;
8681 }
8682
8683 else if ( ( section_version > V_TILES ))
8684 {
8685 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8686 return 0;
8687
8688 }
8689 else
8690 {
8691 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8692 }
8693
8694 int32_t index = 0;
8695 int32_t count = 0;
8696
8697 //tile id
8698 if(!p_igetl(&index,f))
8699 {
8700 return 0;
8701 }
8702 al_trace("Reading tile: index(%d)\n", index);
8703
8704 //tile count
8705 if(!p_igetl(&count,f))
8706 {
8707 return 0;
8708 }
8709 al_trace("Reading tile: count(%d)\n", count);
8710
8711
8712 for ( int32_t tilect = 0; tilect < count; tilect++ )
8713 {
8714 byte *temp_tile = new byte[tilesize(tf32Bit)];
8715 byte format=tf4Bit;
8716 memset(temp_tile, 0, tilesize(tf32Bit));
8717 if(!p_getc(&format,f))
8718 {
8719 delete[] temp_tile;
8720 return 0;
8721 }
8722
8723
8724 if(!pfread(temp_tile,tilesize(format),f))
8725 {
8726 delete[] temp_tile;
8727 return 0;
8728 }
8729
8730 reset_tile(newtilebuf, start+(tilect), format);
8731 if ( skip )
8732 {
8733 if ( (start+(tilect)) < skip )
8734 {
8735 delete[] temp_tile;
8736 continue;
8737 }
8738
8739 }
8740 if ( start+(tilect) < NEWMAXTILES )
8741 {
8742 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8743 }
8744 delete[] temp_tile;
8745
8746 }
8747
8748
8749 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8750
8751 register_blank_tiles();
8752 register_used_tiles();
8753
8754 return 1;
8755
8756 }
8757
8758
8759 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8760 {
8761 dword section_version=0;
8762 int32_t zversion = 0;
8763 int32_t zbuild = 0;
8764
8765 if(!p_igetl(&zversion,f))
8766 {
8767 return 0;
8768 }
8769 if(!p_igetl(&zbuild,f))
8770 {
8771 return 0;
8772 }
8773 if(!p_igetw(&section_version,f))
8774 {
8775 return 0;
8776 }
8777 if(!read_deprecated_section_cversion(f))
8778 {
8779 return 0;
8780 }
8781 al_trace("readoneweapon section_version: %d\n", section_version);
8782
8783 if ( zversion > ZELDA_VERSION )
8784 {
8785 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8786 return 0;
8787 }
8788
8789 else if ( ( section_version > V_TILES ))
8790 {
8791 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8792 return 0;
8793
8794 }
8795 else
8796 {
8797 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8798 }
8799
8800 int32_t index = 0;
8801 int32_t count = 0;
8802
8803 //tile id
8804 if(!p_igetl(&index,f))
8805 {
8806 return 0;
8807 }
8808 al_trace("Reading tile: index(%d)\n", index);
8809
8810 //tile count
8811 if(!p_igetl(&count,f))
8812 {
8813 return 0;
8814 }
8815 al_trace("Reading tile: count(%d)\n", count);
8816
8817
8818
8819
8820 for ( int32_t tilect = 0; tilect < count; tilect++ )
8821 {
8822 byte *temp_tile = new byte[tilesize(tf32Bit)];
8823 byte format=tf4Bit;
8824 memset(temp_tile, 0, tilesize(tf32Bit));
8825
8826 if(!p_getc(&format,f))
8827 {
8828 delete[] temp_tile;
8829 return 0;
8830 }
8831
8832
8833 if(!pfread(temp_tile,tilesize(format),f))
8834 {
8835 delete[] temp_tile;
8836 return 0;
8837 }
8838
8839 reset_tile(newtilebuf, start+(tilect), format);
8840 if ( start+(tilect) < NEWMAXTILES )
8841 {
8842 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8843 }
8844 delete[] temp_tile;
8845 }
8846
8847
8848 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8849
8850 register_blank_tiles();
8851 register_used_tiles();
8852
8853 return 1;
8854
8855 }
8856 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8857 {
8858 dword section_version=V_TILES;
8859 int32_t zversion = ZELDA_VERSION;
8860 int32_t zbuild = VERSION_BUILD;
8861
8862 if(!p_iputl(zversion,f))
8863 {
8864 return 0;
8865 }
8866 if(!p_iputl(zbuild,f))
8867 {
8868 return 0;
8869 }
8870 if(!p_iputw(section_version,f))
8871 {
8872 return 0;
8873 }
8874
8875 if(!write_deprecated_section_cversion(section_version,f))
8876 {
8877 return 0;
8878 }
8879
8880 //start tile id
8881 if(!p_iputl(index,f))
8882 {
8883 return 0;
8884 }
8885
8886 //count
8887 if(!p_iputl(count,f))
8888 {
8889 return 0;
8890 }
8891
8892 for ( int32_t tilect = 0; tilect < count; tilect++ )
8893 {
8894 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8895 {
8896 return 0;
8897 }
8898 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8899 {
8900 return 0;
8901 }
8902 }
8903
8904 return 1;
8905
8906 }
8907
8908 static int32_t _selected_tile=-1, _selected_tcset=-1;
8909 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8910 {
8911 popup_zqdialog_start();
8912 reset_combo_animations();
8913 reset_combo_animations2();
8914 bound(tile,0,NEWMAXTILES-1);
8915 ex=exnow;
8916 int32_t done=0;
8917 int32_t oflip=flip;
8918 int32_t otile=tile;
8919 int32_t ocs=cs;
8920 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8921 int32_t copy=-1;
8922 int32_t tile2=tile,copycnt=0;
8923 reftile = 0;
8924 int32_t tile_clicked=-1;
8925 bool rect_sel=true;
8926 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8927 position_mouse_z(0);
8928
8929 register_used_tiles();
8930 int32_t w = 640;
8931 int32_t h = 480;
8932 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8933 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8934 int32_t screen_xofs=window_xofs+6;
8935 int32_t screen_yofs=window_yofs+25;
8936 int32_t panel_yofs=3;
8937 int32_t mul = 2;
8938 FONT *tfont = get_zc_font(font_lfont_l);
8939
8940 draw_tile_list_window();
8941 draw_tiles(first,cs);
8942
8943 if(type==0)
8944 {
8945 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
8946 }
8947 else
8948 {
8949 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
8950 }
8951 anim_hw_screen();
8952
8953 go_tiles();
8954
8955 while(gui_mouse_b()) rest(1);
8956
8957 bool bdown=false;
8958
8959 #define FOREACH_START(_t) \
8960 { \
8961 int32_t _first, _last; \
8962 if(is_rect) \
8963 { \
8964 _first=top*TILES_PER_ROW+left; \
8965 _last=_first+rows*TILES_PER_ROW|+columns-1; \
8966 } \
8967 else \
8968 { \
8969 _first=zc_min(tile, tile2); \
8970 _last=zc_max(tile, tile2); \
8971 } \
8972 for(int32_t _t=_first; _t<=_last; _t++) \
8973 { \
8974 if(is_rect) \
8975 { \
8976 int32_t row=TILEROW(_t); \
8977 if(row<top || row>=top+rows) \
8978 continue; \
8979 int32_t col=TILECOL(_t); \
8980 if(col<left || col>=left+columns) \
8981 continue; \
8982 } \
8983
8984 #define FOREACH_END\
8985 } \
8986 }
8987
8988 bool did_snap = false;
8989 int otl = tile, otl2 = tile2;
8990 do
8991 {
8992 HANDLE_CLOSE_ZQDLG();
8993 if(exiting_program) break;
8994 //rest(4);
8995 int32_t top=TILEROW(zc_min(tile, tile2));
8996 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
8997 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
8998 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
8999 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9000 bool redraw=false;
9001
9002 if(mouse_z!=0)
9003 {
9004 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9005 position_mouse_z(0);
9006 redraw=true;
9007 }
9008
9009 if(keypressed())
9010 {
9011 switch(readkey()>>8)
9012 {
9013 case KEY_ENTER_PAD:
9014 case KEY_ENTER:
9015 done=2;
9016 break;
9017
9018 case KEY_ESC:
9019 done=1;
9020 break;
9021
9022 case KEY_F1:
9023 onHelp();
9024 break;
9025
9026 case KEY_EQUALS:
9027 case KEY_PLUS_PAD:
9028 {
9029 if(CHECK_CTRL_CMD ||
9030 key[KEY_ALT] || key[KEY_ALTGR])
9031 {
9032 FOREACH_START(t)
9033 if(key[KEY_ALT] || key[KEY_ALTGR])
9034 shift_tile_colors(t, 16, false);
9035 else
9036 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9037 FOREACH_END
9038
9039 register_blank_tiles();
9040 }
9041 else if(edit_cs)
9042 cs = (cs<13) ? cs+1:0;
9043
9044 redraw=true;
9045 break;
9046 }
9047
9048 case KEY_Z:
9049 case KEY_F12:
9050 {
9051 if(!did_snap)
9052 {
9053 //Export tile page as screenshot
9054 PALETTE temppal;
9055 get_palette(temppal);
9056 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9057 draw_tiles(tempbmp,first,cs,false,true);
9058 save_bitmap(getSnapName(), tempbmp, RAMpal);
9059 destroy_bitmap(tempbmp);
9060
9061 redraw = true;
9062 did_snap = true;
9063 }
9064 break;
9065 }
9066
9067 case KEY_S:
9068 {
9069 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9070 break;
9071 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9072 if(!f) break;
9073 al_trace("Saving tile: %d\n", tile);
9074 writetilefile(f,tile,1);
9075 pack_fclose(f);
9076 break;
9077 }
9078 case KEY_L:
9079 {
9080 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9081 break;
9082 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9083 if(!f) break;
9084 al_trace("Saving tile: %d\n", tile);
9085 if (!readtilefile(f))
9086 {
9087 al_trace("Could not read from .ztile packfile %s\n", temppath);
9088 displayinfo("ZTILE File: Error","Could not load the specified Tile.");
9089 }
9090 else
9091 {
9092 displayinfo("ZTILE File: Success!","Loaded the source tiles to your tile sheets!");
9093 }
9094
9095 pack_fclose(f);
9096 //register_blank_tiles();
9097 //register_used_tiles();
9098 redraw=true;
9099 break;
9100 }
9101 case KEY_MINUS:
9102 case KEY_MINUS_PAD:
9103 {
9104 if(CHECK_CTRL_CMD ||
9105 key[KEY_ALT] || key[KEY_ALTGR])
9106 {
9107 FOREACH_START(t)
9108 if(key[KEY_ALT] || key[KEY_ALTGR])
9109 shift_tile_colors(t, -16, false);
9110 else
9111 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9112 FOREACH_END
9113
9114 register_blank_tiles();
9115 }
9116 else if(edit_cs)
9117 cs = (cs>0) ? cs-1:13;
9118
9119 redraw=true;
9120 break;
9121 }
9122
9123 case KEY_UP:
9124 {
9125 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9126 {
9127 case 3: //ALT and CTRL
9128 case 2: //ALT
9129 if(is_rect)
9130 {
9131 mark_save_dirty();
9132 go_slide_tiles(columns, rows, top, left);
9133 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9134 bool same = true;
9135
9136 for(int32_t d=0; d<columns; d++)
9137 {
9138 for(int32_t s=0; s<rows; s++)
9139 {
9140 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9141
9142 if(newtilebuf[t].format!=bitcheck) same = false;
9143 }
9144 }
9145
9146 if(!same) break;
9147
9148 // This used to do something. Too lazy to remove.
9149 // Can probably remove the above "same" check too.
9150 bitcheck = 2;
9151
9152 for(int32_t c=0; c<columns; c++)
9153 {
9154 for(int32_t r=0; r<rows; r++)
9155 {
9156 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9157 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9158 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9159
9160 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9161 {
9162 if(pixelrow==15*bitcheck)
9163 {
9164 int32_t srctile=temptile+TILES_PER_ROW;
9165 if(srctile>=NEWMAXTILES)
9166 srctile-=rows*TILES_PER_ROW;
9167 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9168 }
9169
9170 *dest_pixelrow=*src_pixelrow;
9171 dest_pixelrow++;
9172 src_pixelrow++;
9173 }
9174 }
9175
9176 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9177
9178 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9179 {
9180 if((CHECK_CTRL_CMD))
9181 {
9182 *dest_pixelrow=0;
9183 }
9184 else
9185 {
9186 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9187 *dest_pixelrow=*src_pixelrow;
9188 }
9189 }
9190 }
9191 }
9192
9193 register_blank_tiles();
9194 redraw=true;
9195 break;
9196
9197 case 1: //CTRL
9198 case 0: //None
9199 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9200 redraw=true;
9201
9202 default: //Others
9203 break;
9204 }
9205 }
9206 break;
9207
9208 case KEY_DOWN:
9209 {
9210 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9211 {
9212 case 3: //ALT and CTRL
9213 case 2: //ALT
9214 if(is_rect)
9215 {
9216 mark_save_dirty();
9217 go_slide_tiles(columns, rows, top, left);
9218 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9219 bool same = true;
9220
9221 for(int32_t c=0; c<columns; c++)
9222 {
9223 for(int32_t r=0; r<rows; r++)
9224 {
9225 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9226
9227 if(newtilebuf[t].format!=bitcheck) same = false;
9228 }
9229 }
9230
9231 if(!same) break;
9232
9233 // This used to do something. Too lazy to remove.
9234 // Can probably remove the above "same" check too.
9235 bitcheck = 2;
9236
9237 for(int32_t c=0; c<columns; c++)
9238 {
9239 for(int32_t r=rows-1; r>=0; r--)
9240 {
9241 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9242 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9243 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9244
9245 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9246 {
9247 if(pixelrow<bitcheck)
9248 {
9249 int32_t srctile=temptile-TILES_PER_ROW;
9250 if(srctile<0)
9251 srctile+=rows*TILES_PER_ROW;
9252 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9253 *dest_pixelrow=*tempsrc;
9254 //*dest_pixelrow=0;
9255 }
9256 else
9257 {
9258 *dest_pixelrow=*src_pixelrow;
9259 }
9260
9261 dest_pixelrow--;
9262 src_pixelrow--;
9263 }
9264 }
9265
9266 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9267 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9268
9269 for(int32_t b=0; b<bitcheck; b++)
9270 {
9271 if((CHECK_CTRL_CMD))
9272 {
9273 *dest_pixelrow=0;
9274 }
9275 else
9276 {
9277 *dest_pixelrow=*src_pixelrow;
9278 }
9279
9280 dest_pixelrow++;
9281 src_pixelrow++;
9282 }
9283 }
9284 }
9285
9286 register_blank_tiles();
9287 redraw=true;
9288 break;
9289
9290 case 1: //CTRL
9291 case 0: //None
9292 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9293 redraw=true;
9294
9295 default: //Others
9296 break;
9297 }
9298 }
9299 break;
9300
9301 case KEY_LEFT:
9302 {
9303 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9304 {
9305 case 3: //ALT and CTRL
9306 case 2: //ALT
9307 if(is_rect)
9308 {
9309 mark_save_dirty();
9310 go_slide_tiles(columns, rows, top, left);
9311 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9312 bool same = true;
9313
9314 for(int32_t c=0; c<columns; c++)
9315 {
9316 for(int32_t r=0; r<rows; r++)
9317 {
9318 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9319
9320 if(newtilebuf[t].format!=bitcheck) same = false;
9321 }
9322 }
9323
9324 if(!same) break;
9325
9326 // This used to do something. Too lazy to remove.
9327 // Can probably remove the above "same" check too.
9328 bitcheck = 2;
9329
9330 for(int32_t r=0; r<rows; r++)
9331 {
9332 for(int32_t c=0; c<columns; c++)
9333 {
9334 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9335 byte *dest_pixelrow=(newtilebuf[temptile].data);
9336
9337 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9338 {
9339 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9340 {
9341 *dest_pixelrow=*(dest_pixelrow+1);
9342 dest_pixelrow++;
9343 }
9344
9345 if(c==columns-1)
9346 {
9347 if(!(CHECK_CTRL_CMD))
9348 {
9349 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9350 *dest_pixelrow=*tempsrc;
9351 }
9352 }
9353 else
9354
9355 {
9356 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9357 *dest_pixelrow=*tempsrc;
9358 }
9359
9360 dest_pixelrow++;
9361 }
9362 }
9363 }
9364
9365 register_blank_tiles();
9366 redraw=true;
9367 }
9368
9369 break;
9370
9371 case 1: //CTRL
9372 case 0: //None
9373 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9374 redraw=true;
9375
9376 default: //Others
9377 break;
9378 }
9379 }
9380 break;
9381
9382 case KEY_RIGHT:
9383 {
9384 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9385 {
9386 case 3: //ALT and CTRL
9387 case 2: //ALT
9388 if(is_rect)
9389 {
9390 mark_save_dirty();
9391 go_slide_tiles(columns, rows, top, left);
9392 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9393 bool same = true;
9394
9395 for(int32_t c=0; c<columns; c++)
9396 {
9397 for(int32_t r=0; r<rows; r++)
9398 {
9399 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9400
9401 if(newtilebuf[t].format!=bitcheck) same = false;
9402 }
9403 }
9404
9405 if(!same) break;
9406
9407 // This used to do something. Too lazy to remove.
9408 // Can probably remove the above "same" check too.
9409 bitcheck = 2;
9410
9411 for(int32_t r=0; r<rows; r++)
9412 {
9413 for(int32_t c=columns-1; c>=0; c--)
9414 {
9415 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9416 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9417
9418 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9419 {
9420 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9421 {
9422 *dest_pixelrow=*(dest_pixelrow-1);
9423 dest_pixelrow--;
9424 }
9425
9426 if(c==0)
9427 {
9428 if(!(CHECK_CTRL_CMD))
9429 {
9430 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9431 *dest_pixelrow=*tempsrc;
9432 }
9433 }
9434 else
9435 {
9436 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9437 *dest_pixelrow=*tempsrc;
9438 }
9439
9440 dest_pixelrow--;
9441 }
9442 }
9443 }
9444
9445 register_blank_tiles();
9446 redraw=true;
9447 }
9448
9449 break;
9450
9451 case 1: //CTRL
9452 case 0: //None
9453 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9454 redraw=true;
9455
9456 default: //Others
9457 break;
9458 }
9459 }
9460 break;
9461
9462 case KEY_PGUP:
9463 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9464 redraw=true;
9465 break;
9466
9467 case KEY_PGDN:
9468 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9469 redraw=true;
9470 break;
9471
9472 case KEY_HOME:
9473 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9474 redraw=true;
9475 break;
9476
9477 case KEY_END:
9478 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9479 redraw=true;
9480 break;
9481
9482 case KEY_P:
9483 {
9484 if (auto num = call_get_num("Goto Page", (PreFillComboEditorPage?(first/TILES_PER_PAGE):0), NEWMAXTILES/TILES_PER_PAGE))
9485 sel_tile(tile, tile2, first, type, ((*num-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9486 break;
9487 }
9488
9489 case KEY_O:
9490 if(type==0 && copy>=0)
9491 {
9492 go_tiles();
9493
9494 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9495 {
9496 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9497 mark_save_dirty();
9498 }
9499 else
9500 {
9501 if (overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD)))
9502 mark_save_dirty();
9503 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9504 }
9505
9506 mark_save_dirty();
9507 redraw=true;
9508 }
9509
9510 break;
9511
9512 case KEY_E:
9513 if(type==0)
9514 {
9515 edit_tile(tile,flip,cs);
9516 draw_tile_list_window();
9517 redraw=true;
9518 }
9519
9520 break;
9521
9522 case KEY_G:
9523 if(type==0)
9524 {
9525 grab_tile(tile,cs);
9526 draw_tile_list_window();
9527 redraw=true;
9528 }
9529
9530 break;
9531
9532 case KEY_C:
9533 copy=zc_min(tile,tile2);
9534 copycnt=abs(tile-tile2)+1;
9535 redraw=true;
9536 break;
9537
9538 case KEY_X:
9539 if(type==2)
9540 {
9541 ex=(ex+1)%3;
9542 }
9543
9544 break;
9545
9546 case KEY_R:
9547 if(type==2)
9548 break;
9549 if(type==1)
9550 {
9551 flip = rotate_value(flip);
9552 redraw=true;
9553 break;
9554 }
9555
9556 go_tiles();
9557
9558 if(CHECK_CTRL_CMD)
9559 {
9560 bool go=false;
9561 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9562 go=true;
9563 else if(massRecolorSetup(cs))
9564 go=true;
9565
9566 if(go)
9567 {
9568 FOREACH_START(t)
9569 massRecolorApply(t);
9570 FOREACH_END
9571
9572 register_blank_tiles();
9573 }
9574 }
9575 else
9576 {
9577 FOREACH_START(t)
9578 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9579 FOREACH_END
9580 }
9581
9582 redraw=true;
9583 mark_save_dirty();
9584 break;
9585
9586 case KEY_SPACE:
9587 rect_sel=!rect_sel;
9588 copy=-1;
9589 redraw=true;
9590 break;
9591
9592 case KEY_H:
9593 flip^=1;
9594 go_tiles();
9595
9596 if(type==0)
9597 {
9598 normalize(tile,tile2,rect_sel,flip);
9599 flip=0;
9600 }
9601
9602 redraw=true;
9603 break;
9604
9605
9606 case KEY_V:
9607 if(copy==-1)
9608 {
9609 if(type!=2)
9610 {
9611 flip^=2;
9612 go_tiles();
9613
9614 if(type==0)
9615 {
9616 normalize(tile,tile2,rect_sel,flip);
9617 flip=0;
9618 }
9619 }
9620 }
9621 else
9622 {
9623 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9624 go_tiles();
9625 if (copy_tiles(tile,tile2,copy,copycnt,rect_sel,false))
9626 mark_save_dirty();
9627 }
9628
9629 redraw=true;
9630 break;
9631
9632 case KEY_F:
9633 if(copy==-1)
9634 {
9635 break;
9636 }
9637 else
9638 {
9639 go_tiles();
9640 {
9641 if (copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false))
9642 mark_save_dirty();
9643 }
9644 }
9645
9646 redraw=true;
9647 break;
9648
9649 case KEY_DEL:
9650 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9651 {
9652 bool warn = (rect_sel
9653 && ((tile/20)!=(tile2/20))
9654 && !(tile%20==0&&tile2%20==19));
9655 int32_t z=zc_min(tile,tile2);
9656 int32_t count = abs(tile-tile2) + 1;
9657 tile=z;
9658 tile2=NEWMAXTILES;
9659 copy = tile + count;
9660 copycnt = NEWMAXTILES-copy;
9661 char buf[64];
9662
9663 if(count>1)
9664 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9665 else
9666 sprintf(buf,"Remove tile %d?",tile);
9667
9668 if (alert_confirm("Remove Tiles", std::string(buf)
9669 +"\nThis will offset the tiles that follow!"
9670 +(warn?"\nRemoving tiles ignores rectangular selections!":"")))
9671 {
9672 go_tiles();
9673 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9674 {
9675 redraw=true;
9676 mark_save_dirty();
9677 }
9678 }
9679 }
9680 delete_tiles(tile,tile2,rect_sel);
9681 redraw=true;
9682 break;
9683
9684 case KEY_U:
9685 {
9686 if(CHECK_CTRL_CMD)
9687 {
9688 //Only toggle the first 2 bits!
9689 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9690 }
9691 else
9692 {
9693 comeback_tiles();
9694 }
9695
9696 redraw=true;
9697 }
9698 break;
9699
9700 case KEY_8:
9701 case KEY_8_PAD:
9702 hide_8bit_marker();
9703 break;
9704
9705 case KEY_I: //insert tiles
9706 if(type==0)
9707 {
9708 bool warn = (rect_sel
9709 && ((tile/20)!=(tile2/20))
9710 && !(tile%20==0&&tile2%20==19));
9711 int32_t z=zc_min(tile,tile2);
9712 int32_t count = abs(tile-tile2) + 1;
9713 tile=z;
9714 tile2=NEWMAXTILES;
9715 copy = tile + count;
9716 copycnt = NEWMAXTILES-copy;
9717
9718 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9719 {
9720 char buf[64];
9721
9722 if(count>1)
9723 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9724 else
9725 sprintf(buf,"Remove tile %d?",tile);
9726
9727 if (alert_confirm("Remove Tiles", std::string(buf)
9728 +"\nThis will offset the tiles that follow!"
9729 +(warn?"\nRemoving tiles ignores rectangular selections!":"")))
9730 {
9731 go_tiles();
9732 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9733 {
9734 redraw=true;
9735 mark_save_dirty();
9736 }
9737 }
9738 }
9739 else
9740 {
9741 char buf[64];
9742
9743 if(count>1)
9744 sprintf(buf,"Insert %d blank tiles?",count);
9745 else
9746 sprintf(buf,"Insert a blank tile?");
9747
9748 if (alert_confirm("Insert Tiles", std::string(buf)
9749 +"\nThis will offset the tiles that follow!"
9750 +(warn?"\nInserting tiles ignores rectangular selections!":"")))
9751 {
9752 go_tiles();
9753 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9754 {
9755 redraw=true;
9756 mark_save_dirty();
9757 }
9758 }
9759 }
9760
9761 copy=-1;
9762 tile2=tile=z;
9763 }
9764 break;
9765 case KEY_M:
9766 if(type==0)
9767 {
9768 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9769 {
9770 go_tiles();
9771 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9772 mark_save_dirty();
9773 }
9774 else if(copy==-1)
9775 {
9776 // I don't know what this was supposed to be doing before.
9777 // It didn't work in anything like a sensible way.
9778 if(rect_sel)
9779 {
9780 make_combos_rect(top, left, rows, columns, cs);
9781 }
9782 else
9783 {
9784 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9785 }
9786 }
9787
9788 redraw=true;
9789 }
9790 break;
9791
9792 case KEY_D:
9793 {
9794 int32_t frames=1;
9795 char buf[80];
9796 sprintf(buf, "%d", frames);
9797 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9798 create_relational_tiles_dlg[2].dp=buf;
9799
9800 large_dialog(create_relational_tiles_dlg);
9801
9802 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9803
9804 if(ret==5)
9805 {
9806 frames=zc_max(atoi(buf),1);
9807 bool same = true;
9808 int32_t bitcheck=newtilebuf[tile].format;
9809
9810 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9811 {
9812 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9813 }
9814
9815 if(!same)
9816 {
9817 displayinfo("Error","The source tiles are not in the same format.");
9818 break;
9819 }
9820
9821 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9822 {
9823 displayinfo("Error","Too many tiles will be created");
9824 break;
9825 }
9826
9827 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9828 {
9829 reset_tile(newtilebuf, tile+i, bitcheck);
9830 }
9831
9832 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9833 {
9834 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9835 {
9836 for(int32_t j=0; j<frames; ++j)
9837 {
9838 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9839 }
9840 }
9841 }
9842 else
9843 {
9844 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9845 {
9846 for(int32_t j=0; j<frames; ++j)
9847 {
9848 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9849 }
9850 }
9851 }
9852 }
9853 register_blank_tiles();
9854 register_used_tiles();
9855 redraw=true;
9856 mark_save_dirty();
9857 break;
9858 }
9859
9860 case KEY_B:
9861 {
9862 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9863 bool control=(CHECK_CTRL_CMD);
9864 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9865 int format = control ? tf4Bit : tf8Bit;
9866
9867 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9868 register_blank_tiles();
9869 }
9870 break;
9871 }
9872
9873 clear_keybuf();
9874 }
9875
9876 if(!(key[KEY_Z] || key[KEY_F12]))
9877 did_snap = false;
9878
9879 if(gui_mouse_b()&1)
9880 {
9881 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9882 {
9883 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9884 {
9885 done=1;
9886 }
9887 }
9888
9889 int32_t x=gui_mouse_x()-screen_xofs;
9890 int32_t y=gui_mouse_y()-screen_yofs;
9891
9892 if(y>=0 && y<208*mul)
9893 {
9894 x=zc_min(zc_max(x,0),(320*mul)-1);
9895 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9896
9897 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9898 {
9899 tile2=t;
9900 }
9901 else
9902 {
9903 tile=tile2=t;
9904 }
9905
9906 if(tile_clicked!=t)
9907 {
9908 dclick_status=DCLICK_NOT;
9909 }
9910 else if(dclick_status == DCLICK_AGAIN)
9911 {
9912 while(gui_mouse_b()) rest(1);
9913
9914 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
9915 {
9916 dclick_status=DCLICK_NOT;
9917 }
9918 else
9919 {
9920 if(type==0)
9921 {
9922 edit_tile(tile,flip,cs);
9923 draw_tile_list_window();
9924 redraw=true;
9925 }
9926 else
9927 {
9928 done=2;
9929 }
9930 }
9931 }
9932
9933 tile_clicked=t;
9934 }
9935 else if(x>300*mul && !bdown)
9936 {
9937 if(y<224*mul && first>0)
9938 {
9939 first-=TILES_PER_PAGE;
9940 redraw=true;
9941 }
9942
9943 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
9944 {
9945 first+=TILES_PER_PAGE;
9946 redraw=true;
9947 }
9948
9949 bdown=true;
9950 }
9951
9952 if(type==1||type==2)
9953 {
9954 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
9955 done=1;
9956
9957 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
9958 done=2;
9959 }
9960 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
9961 {
9962 rect_sel=!rect_sel;
9963 copy=-1;
9964 redraw=true;
9965 }
9966 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
9967 {
9968 FONT *tf = font;
9969 font = tfont;
9970
9971 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
9972 {
9973 font = tf;
9974 grab_tile(tile,cs);
9975 draw_tile_list_window();
9976 position_mouse_z(0);
9977 redraw=true;
9978 }
9979
9980 font = tf;
9981 }
9982 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
9983 {
9984 FONT *tf = font;
9985 font = tfont;
9986
9987 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
9988 {
9989 font = tf;
9990 edit_tile(tile,flip,cs);
9991 draw_tile_list_window();
9992 redraw=true;
9993 }
9994
9995 font = tf;
9996 }
9997 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
9998 {
9999 FONT *tf = font;
10000 font = tfont;
10001
10002 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10003 {
10004 std::string initial_path = "tileset.png";
10005 if (strlen(datapath))
10006 initial_path = fmt::format("{}/{}", datapath, initial_path);
10007 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10008 {
10009 PALETTE temppal;
10010 get_palette(temppal);
10011 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10012 draw_tiles(tempbmp,first,cs,false,true);
10013 save_bitmap(temppath, tempbmp, RAMpal);
10014 destroy_bitmap(tempbmp);
10015 }
10016 }
10017
10018 font = tf;
10019 }
10020 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10021 {
10022 FONT *tf = font;
10023 font = tfont;
10024
10025 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10026 {
10027 if(massRecolorSetup(cs))
10028 {
10029 go_tiles();
10030
10031 FOREACH_START(t)
10032 massRecolorApply(t);
10033 FOREACH_END
10034
10035 register_blank_tiles();
10036 }
10037 }
10038
10039 font = tf;
10040 }
10041 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10042 {
10043 FONT *tf = font;
10044 font = tfont;
10045
10046 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10047 {
10048 done=1;
10049 }
10050
10051 font = tf;
10052 }
10053
10054 bdown=true;
10055 }
10056
10057 bool r_click = false;
10058 bool force_draw_select = false;
10059 if(gui_mouse_b()&2 && !bdown && type==0)
10060 {
10061 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10062 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10063
10064 if(y>=0 && y<208*mul)
10065 {
10066 x=zc_min(zc_max(x,0),(320*mul)-1);
10067 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10068
10069 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10070 tile=tile2=t;
10071 }
10072
10073 bdown = r_click = true;
10074 force_draw_select = true;
10075 }
10076
10077 if(gui_mouse_b()==0)
10078 bdown=false;
10079
10080 position_mouse_z(0);
10081
10082 REDRAW:
10083
10084 if(!(framecnt%8) || force_draw_select || InvalidBG == 1)
10085 redraw=true;
10086 if(otl != tile || otl2 != tile2)
10087 {
10088 otl = tile;
10089 otl2 = tile2;
10090 redraw = true;
10091 }
10092
10093 if(redraw)
10094 {
10095 draw_tiles(first,cs);
10096 if(force_draw_select || (framecnt&8))
10097 {
10098 if(rect_sel)
10099 {
10100 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10101 zc_min(TILECOL(tile),TILECOL(tile2));
10102 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10103 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10104 {
10105 if(i>=first && i<first+TILES_PER_PAGE &&
10106 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10107 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10108 {
10109 int32_t x=TILECOL(i)<<(5);
10110 int32_t y=TILEROW(i-first)<<(5);
10111 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10112 }
10113 }
10114 }
10115 else
10116 {
10117 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10118 {
10119 if(i>=first && i<first+TILES_PER_PAGE)
10120 {
10121 int32_t x=TILECOL(i)<<(5);
10122 int32_t y=TILEROW(i-first)<<(5);
10123 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10124 }
10125 }
10126 }
10127 }
10128
10129 if(type==0)
10130 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10131 else
10132 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10133
10134 if(type==2)
10135 {
10136 char cbuf[16];
10137 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10138 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10139 }
10140 }
10141 anim_hw_screen();
10142
10143 if(r_click)
10144 {
10145 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10146 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10147 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10148 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10149
10150 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10151 if (newtilebuf[tile].format == tf8Bit)
10152 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10153 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10154 select_tile_color_depth_cb = [&](int format){
10155 if (newtilebuf[tile].format == format)
10156 return;
10157
10158 bool skip_prompt = true;
10159 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10160 };
10161
10162 NewMenu rcmenu
10163 {
10164 { "Copy", [&]()
10165 {
10166 copy = zc_min(tile,tile2);
10167 copycnt = abs(tile-tile2)+1;
10168 } },
10169 { "Paste", [&]()
10170 {
10171 if (copy_tiles(tile, tile2, copy, copycnt, rect_sel, false))
10172 mark_save_dirty();
10173 }, nullopt, copy < 0 ? MFL_DIS : 0 },
10174 { "Move", [&]()
10175 {
10176 if (copy_tiles(tile, tile2, copy, copycnt, rect_sel, true))
10177 mark_save_dirty();
10178 }, nullopt, copy < 0 ? MFL_DIS : 0 },
10179 { "Clear", [&]()
10180 {
10181 delete_tiles(tile, tile2, rect_sel);
10182 } },
10183 { "Set as Reference", [&]()
10184 {
10185 reftile = tile;
10186 } },
10187 {},
10188 { "Edit", [&]()
10189 {
10190 edit_tile(tile, flip, cs);
10191 draw_tile_list_window();
10192 } },
10193 { "Grab", [&]()
10194 {
10195 grab_tile(tile, cs);
10196 draw_tile_list_window();
10197 position_mouse_z(0);
10198 } },
10199 { "Scale", [&]()
10200 {
10201 if (scale_or_rotate_tiles(tile, tile2, cs, false))
10202 mark_save_dirty();
10203 }, nullopt, type != 0 ? MFL_DIS : 0 },
10204 { "Angular Rotation", [&]()
10205 {
10206 if (scale_or_rotate_tiles(tile, tile2, cs, true))
10207 mark_save_dirty();
10208 }, nullopt, type != 0 ? MFL_DIS : 0 },
10209 { "Color Depth", &select_tile_color_depth_menu },
10210 {},
10211 { "Blank?", [&]()
10212 {
10213 show_blank_tile(tile);
10214 } },
10215 {},
10216 { "View ", &select_tile_view_menu },
10217 { "Overlay", [&]()
10218 {
10219 overlay_tile(newtilebuf, tile, copy, cs, 0);
10220 } },
10221 { "H-Flip", [&]()
10222 {
10223 flip ^= 1;
10224 go_tiles();
10225
10226 if(type == 0)
10227 {
10228 normalize(tile, tile2, rect_sel, flip);
10229 flip = 0;
10230 }
10231 } },
10232 { "V-Flip", [&]()
10233 {
10234 flip ^= 2;
10235 go_tiles();
10236
10237 if(type == 0)
10238 {
10239 normalize(tile, tile2, rect_sel, flip);
10240 flip = 0;
10241 }
10242 } },
10243 { "Create Combos", [&]()
10244 {
10245 if(rect_sel)
10246 make_combos_rect(top, left, rows, columns, cs);
10247 else
10248 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10249 }, nullopt, type != 0 ? MFL_DIS : 0 },
10250 { "Insert", [&]()
10251 {
10252 bool warn = (rect_sel
10253 && ((tile/20)!=(tile2/20))
10254 && !(tile%20==0&&tile2%20==19));
10255 int32_t z = zc_min(tile, tile2);
10256 int32_t count = abs(tile-tile2) + 1;
10257 tile = z;
10258 tile2 = NEWMAXTILES;
10259 copy = tile + count;
10260 copycnt = NEWMAXTILES-copy;
10261
10262 string msg;
10263
10264 if(count>1)
10265 msg = fmt::format("Insert {} blank tiles?",count);
10266 else
10267 msg = "Insert a blank tile?";
10268
10269 if (alert_confirm("Insert Tiles", msg
10270 +"\nThis will offset the tiles that follow!"
10271 +(warn?"\nInserting tiles ignores rectangular selections!":"")))
10272 {
10273 go_tiles();
10274 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10275 mark_save_dirty();
10276 }
10277
10278 copy=-1;
10279 tile2=tile=z;
10280 }, nullopt, type != 0 ? MFL_DIS : 0 },
10281 { "Remove", [&]()
10282 {
10283 bool warn = (rect_sel
10284 && ((tile/20)!=(tile2/20))
10285 && !(tile%20==0&&tile2%20==19));
10286 int32_t z = zc_min(tile, tile2);
10287 int32_t count = abs(tile-tile2) + 1;
10288 tile = z;
10289 tile2 = NEWMAXTILES;
10290 copy = tile + count;
10291 copycnt = NEWMAXTILES-copy;
10292
10293 string msg;
10294
10295 if(count>1)
10296 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10297 else
10298 msg = fmt::format("Remove tile {}?", tile);
10299
10300 if (alert_confirm("Remove Tiles", msg
10301 +"\nThis will offset the tiles that follow!"
10302 +(warn?"\nRemoving tiles ignores rectangular selections!":"")))
10303 {
10304 go_tiles();
10305 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10306 mark_save_dirty();
10307 }
10308
10309 copy=-1;
10310 tile2=tile=z;
10311 }, nullopt, type != 0 ? MFL_DIS : 0 },
10312 };
10313 rcmenu.pop(window_mouse_x(),window_mouse_y());
10314 redraw = true;
10315 r_click = false;
10316 goto REDRAW;
10317 }
10318 }
10319 while(!done);
10320
10321 while(gui_mouse_b()) rest(1);
10322
10323 register_blank_tiles();
10324 register_used_tiles();
10325 setup_combo_animations();
10326 setup_combo_animations2();
10327 int32_t ret = done-1;
10328 if(ret)
10329 {
10330 _selected_tile = tile;
10331 _selected_tcset = cs;
10332 }
10333
10334 popup_zqdialog_end();
10335 return ret;
10336 }
10337 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10338 {
10339 if(_selected_tile > -1)
10340 {
10341 tile = _selected_tile;
10342 cs = _selected_tcset;
10343 }
10344 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10345 if(_selected_tile < 0)
10346 {
10347 _selected_tile = tile;
10348 _selected_tcset = cs;
10349 }
10350 return ret;
10351 }
10352
10353 int32_t onTiles()
10354 {
10355 return onGotoTiles(-1);
10356 }
10357
10358 int32_t onGotoTiles(int32_t startfrom)
10359 {
10360 static int32_t t = 0;
10361 if (startfrom > -1)
10362 t = startfrom;
10363 int32_t flip = 0;
10364 int32_t c = CSet;
10365 reset_pal_cycling();
10366 rebuild_trans_table();
10367 select_tile(t, flip, 0, c, true);
10368 refresh(rALL);
10369 return D_O_K;
10370 }
10371
10372 int32_t combopage_animate = 1;
10373 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10374 {
10375 if(unsigned(c)<MAXCOMBOS)
10376 {
10377 newcombo& cmb = combobuf[c];
10378 int t = cmb.tile;
10379 if(!animate)
10380 cmb.tile = cmb.o_tile;
10381 put_combo(dest,x,y,c,cs,0,0);
10382 cmb.tile = t;
10383 }
10384 else
10385 {
10386 rectfill(dest,x,y,x+32-1,y+32-1,0);
10387 }
10388 }
10389
10390 void draw_combos(int32_t page,int32_t cs,bool cols)
10391 {
10392 clear_bitmap(screen2);
10393 BITMAP *buf = create_bitmap_ex(8,16,16);
10394
10395 int32_t w = 32;
10396 int32_t h = 32;
10397 int32_t mul = 2;
10398
10399 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10400 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10401 int32_t screen_xofs=window_xofs+6;
10402 int32_t screen_yofs=window_yofs+25;
10403
10404 if(cols==false)
10405 {
10406 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10407 {
10408 int32_t x = (i%COMBOS_PER_ROW)*w;
10409 int32_t y = (i/COMBOS_PER_ROW)*h;
10410
10411 combotile_override_x = x+screen_xofs+(w-16)/2;
10412 combotile_override_y = y+screen_yofs+(h-16)/2;
10413 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10414 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10415 }
10416 }
10417 else
10418 {
10419 int32_t c = 0;
10420
10421 for(int32_t i=0; i<256; i++)
10422 {
10423 int32_t x = (i%COMBOS_PER_ROW)*w;
10424 int32_t y = (i/COMBOS_PER_ROW)*h;
10425
10426 combotile_override_x = x+screen_xofs+(w-16)/2;
10427 combotile_override_y = y+screen_yofs+(h-16)/2;
10428 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10429 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10430 ++c;
10431
10432 if((i&3)==3)
10433 c+=48;
10434
10435 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10436 c-=256;
10437 }
10438 }
10439 combotile_override_x = combotile_override_y = -1;
10440
10441 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10442 {
10443 vline(screen2,x,0,(208*mul)-1,vc(15));
10444 }
10445
10446 destroy_bitmap(buf);
10447 }
10448
10449 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10450 {
10451 int32_t yofs=3;
10452 static BITMAP *buf = create_bitmap_ex(8,16,16);
10453 int32_t mul = 2;
10454 FONT *tfont = get_zc_font(font_lfont_l);
10455
10456 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10457 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10458 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10459
10460 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10461
10462 if(copy>=0)
10463 {
10464 put_combo(buf,0,0,copy,cs,0,0);
10465 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10466
10467 if(copycnt>1)
10468 {
10469 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10470 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10471 }
10472 else
10473 {
10474 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10475 }
10476 }
10477 else
10478 {
10479 if (InvalidBG == 2)
10480 {
10481 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10482 }
10483 else if(InvalidBG == 1)
10484 {
10485 draw_static(screen2, 31*mul, 216*mul+yofs, 16*mul, 16*mul);
10486 }
10487 else
10488 {
10489 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10490 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10491 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10492 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10493 }
10494 }
10495
10496 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10497 put_combo(buf,0,0,tile,cs,0,0);
10498 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10499
10500 if(tile>tile2)
10501 {
10502 zc_swap(tile,tile2);
10503 }
10504
10505 char cbuf[8];
10506 cbuf[0]=0;
10507
10508 if(tile2!=tile)
10509 {
10510 sprintf(cbuf,"-%d",tile2);
10511 }
10512
10513 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10514 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10515
10516 if(tile2==tile)
10517 {
10518 int32_t nextcombo=combobuf[tile].nextcombo;
10519 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10520 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10521
10522 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10523 {
10524 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10525 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10526 }
10527 else
10528 {
10529 if (InvalidBG == 2)
10530 {
10531 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10532 }
10533 else if(InvalidBG == 1)
10534 {
10535 draw_static(screen2, 136*mul, 216*mul+yofs, 16*mul, 16*mul);
10536 }
10537 else
10538 {
10539 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10540 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10541 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10542 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10543 }
10544 }
10545
10546 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10547 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10548 }
10549
10550
10551 FONT *tf = font;
10552 font = tfont;
10553
10554 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10555 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10556
10557 if(buttons&2)
10558 {
10559 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10560 }
10561
10562 if(buttons&4)
10563 {
10564 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10565 }
10566
10567 font = tf;
10568
10569 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10570 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10571 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10572 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10573
10574 int32_t w = 640;
10575 int32_t h = 480;
10576 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10577 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10578 int32_t screen_xofs=window_xofs+6;
10579 int32_t screen_yofs=window_yofs+25;
10580
10581 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10582 }
10583
10584 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10585 {
10586 int32_t page = tile&0xFF00;
10587 tile &= 0xFF;
10588
10589 if(!cols)
10590 tile += s;
10591 else
10592 {
10593 if(s==-COMBOS_PER_ROW)
10594 tile-=4;
10595
10596 if(s==COMBOS_PER_ROW)
10597 tile+=4;
10598
10599 if(s==-1)
10600 tile-=1;
10601
10602 if(s==1)
10603 tile+=1;
10604 }
10605
10606 /*
10607 if(s==1)
10608 {
10609 if((tile&3)==3)
10610 tile+=48;
10611 else
10612 ++tile;
10613 }
10614 if(s==-1)
10615 {
10616 if((tile&3)==0)
10617 tile-=48;
10618 else
10619 --tile;
10620 }
10621 }
10622 */
10623 bound(tile,0,255);
10624 tile += page;
10625
10626 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10627 tile2 = tile;
10628 }
10629
10630 void draw_combo_list_window()
10631 {
10632 int32_t window_xofs=0;
10633 int32_t window_yofs=0;
10634 int32_t w = 640;
10635 int32_t h = 480;
10636
10637 window_xofs=(zq_screen_w-w-12)>>1;
10638 window_yofs=(zq_screen_h-h-25-6)>>1;
10639 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10640 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10641 FONT *oldfont = font;
10642 font = get_zc_font(font_lfont);
10643 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10644 font=oldfont;
10645 }
10646
10647
10648 static int32_t _selected_combo=-1, _selected_cset=-1;
10649 bool select_combo_2(int32_t &cmb,int32_t &cs)
10650 {
10651 popup_zqdialog_start();
10652 reset_combo_animations();
10653 reset_combo_animations2();
10654 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10655 // static int32_t cmb=0;
10656 int32_t page=cmb>>8;
10657 int32_t tile2=cmb;
10658 int32_t done=0;
10659 int32_t tile_clicked=-1;
10660 int32_t t2;
10661 int32_t copy=-1;
10662 int32_t copycnt=0;
10663
10664 position_mouse_z(0);
10665
10666 int32_t w = 640;
10667 int32_t h = 480;
10668 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10669 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10670 int32_t screen_xofs=window_xofs+6;
10671 int32_t screen_yofs=window_yofs+25;
10672 int32_t panel_yofs=3;
10673 int32_t mul = 2;
10674 FONT *tfont = get_zc_font(font_lfont_l);
10675
10676 draw_combo_list_window();
10677 draw_combos(page,cs,true);
10678 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10679 anim_hw_screen();
10680
10681 while(gui_mouse_b()) rest(1);
10682
10683 bool bdown=false;
10684 int otl = cmb, otl2 = tile2;
10685
10686 do
10687 {
10688 HANDLE_CLOSE_ZQDLG();
10689 if(exiting_program) break;
10690 //rest(4);
10691
10692 if(mouse_z<0)
10693 {
10694 if(page<COMBO_PAGES-1)
10695 {
10696 ++page;
10697 cmb=tile2=(page<<8)+(cmb&0xFF);
10698 }
10699
10700 position_mouse_z(0);
10701 }
10702 else if(mouse_z>0)
10703 {
10704 if(page>0)
10705 {
10706 --page;
10707 cmb=tile2=(page<<8)+(cmb&0xFF);
10708 }
10709
10710 position_mouse_z(0);
10711 }
10712
10713 if(keypressed())
10714 {
10715 switch(readkey()>>8)
10716 {
10717 case KEY_DEL:
10718 cmb=0;
10719 done=2;
10720 break;
10721
10722 case KEY_ENTER_PAD:
10723 case KEY_ENTER:
10724 done=2;
10725 break;
10726
10727 case KEY_ESC:
10728 done=1;
10729 break;
10730
10731 case KEY_F1:
10732 onHelp();
10733 break;
10734
10735 case KEY_EQUALS:
10736 case KEY_PLUS_PAD:
10737 cs = (cs<13) ? cs+1:0;
10738 break;
10739
10740 case KEY_MINUS:
10741 case KEY_MINUS_PAD:
10742 cs = (cs>0) ? cs-1:13;
10743 break;
10744
10745 case KEY_UP:
10746 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10747 break;
10748
10749 case KEY_DOWN:
10750 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10751 break;
10752
10753 case KEY_LEFT:
10754 sel_combo(cmb,tile2,-1,true);
10755 break;
10756
10757 case KEY_RIGHT:
10758 sel_combo(cmb,tile2,1,true);
10759 break;
10760
10761 case KEY_PGUP:
10762 if(page>0)
10763 {
10764 --page;
10765 cmb=tile2=(page<<8)+(cmb&0xFF);
10766 }
10767 break;
10768
10769 case KEY_PGDN:
10770 if(page<COMBO_PAGES-1)
10771 {
10772 ++page;
10773 cmb=tile2=(page<<8)+(cmb&0xFF);
10774 }
10775 break;
10776
10777 case KEY_P:
10778 {
10779 if (auto num = call_get_num("Goto Page", (PreFillComboEditorPage?page:0), COMBO_PAGES-1))
10780 {
10781 page = *num;
10782 cmb = tile2 = (page<<8)+(cmb&0xFF);
10783 }
10784 break;
10785 }
10786 }
10787
10788 clear_keybuf();
10789 }
10790
10791 if(gui_mouse_b()&1)
10792 {
10793 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10794 {
10795 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10796 {
10797 done=1;
10798 }
10799 }
10800
10801 int32_t x=gui_mouse_x()-screen_xofs;
10802 int32_t y=gui_mouse_y()-screen_yofs;
10803
10804 if(y>=0 && y<208*mul)
10805 {
10806 x=zc_min(zc_max(x,0),(320*mul)-1);
10807 int32_t t;
10808
10809 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10810
10811 bound(t,0,255);
10812 t+=page<<8;
10813 cmb=tile2=t;
10814
10815 if(tile_clicked!=t)
10816 {
10817 dclick_status=DCLICK_NOT;
10818 }
10819 else if(dclick_status == DCLICK_AGAIN)
10820 {
10821 while(gui_mouse_b()) rest(1);
10822
10823 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10824
10825 if(t2!=t)
10826 {
10827 dclick_status=DCLICK_NOT;
10828 }
10829 else
10830 {
10831 done=2;
10832 }
10833 }
10834
10835 tile_clicked=t;
10836 }
10837 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10838 {
10839 if(y<(224*mul)+panel_yofs && page>0)
10840 {
10841 --page;
10842 }
10843
10844 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10845 {
10846 ++page;
10847 }
10848
10849 bdown=true;
10850 }
10851
10852 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10853 {
10854 FONT *tf = font;
10855 font = tfont;
10856
10857 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10858 {
10859 done=2;
10860 }
10861
10862 font = tf;
10863 }
10864 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
10865 {
10866 FONT *tf = font;
10867 font = tfont;
10868
10869 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
10870 combopage_animate = combopage_animate ? 0 : 1;
10871 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
10872
10873 font = tf;
10874 }
10875
10876 bdown=true;
10877 }
10878
10879 bool r_click = false;
10880
10881 bool force_draw_select = false;
10882 if(gui_mouse_b()&2 && !bdown)
10883 {
10884 int32_t x=gui_mouse_x()+screen_xofs;
10885 int32_t y=gui_mouse_y()+screen_yofs;
10886
10887 if(y>=0 && y<208*mul)
10888 {
10889 x=zc_min(zc_max(x,0),(320*mul)-1);
10890 int32_t t;
10891
10892 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10893
10894 bound(t,0,255);
10895 t+=page<<8;
10896
10897 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
10898 cmb=tile2=t;
10899 }
10900
10901 bdown = r_click = true;
10902 force_draw_select = true;
10903 }
10904
10905 if(gui_mouse_b()==0)
10906 bdown=false;
10907
10908 if(otl != cmb || otl2 != tile2)
10909 {
10910 otl = cmb;
10911 otl2 = tile2;
10912 }
10913
10914 // if(true) // redraw every frame now. Eyeball combos need to animate regardless, and cursor blinks every 8 frames anyway.
10915 {
10916 draw_combos(page,cs,true);
10917 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10918 if(force_draw_select || (framecnt&8))
10919 {
10920 int32_t x,y;
10921
10922 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
10923 {
10924 if((i>>8)==page)
10925 {
10926 int32_t t=i&255;
10927
10928 x=((t&3) + ((t/52)<<2)) << 5;
10929 y=((t%52)>>2) << 5;
10930
10931 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
10932 }
10933 }
10934 }
10935 }
10936 anim_hw_screen();
10937 }
10938 while(!done);
10939
10940 while(gui_mouse_b()) rest(1);
10941
10942 setup_combo_animations();
10943 setup_combo_animations2();
10944
10945 bool ret = done==2;
10946 if(ret)
10947 {
10948 _selected_combo = cmb;
10949 _selected_cset = cs;
10950 }
10951
10952 popup_zqdialog_end();
10953 return ret;
10954 }
10955
10956 bool select_combo_3(int32_t &cmb,int32_t &cs)
10957 {
10958 if(_selected_combo < 0)
10959 {
10960 _selected_combo = Combo;
10961 _selected_cset = CSet;
10962 }
10963 cmb = _selected_combo;
10964 cs = _selected_cset;
10965 return select_combo_2(cmb,cs);
10966 }
10967
10968 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
10969 {
10970 static bitstring pasteflags;
10971 static const vector<CheckListInfo> advp_names =
10972 {
10973 { "Tile" },
10974 { "CSet2" },
10975 { "Solidity" },
10976 { "Animation" },
10977 { "Type" },
10978 { "Inherent Flag" },
10979 { "Attributes", "Including Attribytes and Attrishorts" },
10980 { "Flags", "The 16 Flags on the 'Flags' tab" },
10981 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
10982 { "Label" },
10983 { "Script" },
10984 { "Effect" },
10985 { "Triggers Tab" },
10986 { "Lifting Tab" },
10987 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
10988 { "Gen: SFX", "The SFX related values from the 'General' tab" },
10989 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
10990 { "Gen: Z Height", "The combo's 'Z Height'/'Z Step Height' settings, and related flags" },
10991 { "Misc Weapon Data", "The combo's 'Misc Weapon Data' settings" },
10992 // should be CMB_ADVP_SZ long
10993 };
10994
10995 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
10996 return false;
10997
10998 //Paste to each combo in the range
10999 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11000 combobuf[i].advpaste(combobuf[copy], pasteflags);
11001
11002 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11003 {
11004 setup_combo_animations();
11005 setup_combo_animations2();
11006 }
11007
11008 return true;
11009 }
11010
11011 int32_t combo_screen(int32_t pg, int32_t tl)
11012 {
11013 popup_zqdialog_start();
11014 reset_combo_animations();
11015 reset_combo_animations2();
11016 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11017 static int32_t tile=0;
11018 static int32_t page=0;
11019
11020 if(pg>-1)
11021 page = pg;
11022
11023 if(tl>-1)
11024 tile = tl;
11025
11026 int32_t tile2=tile;
11027 int32_t done=0;
11028 int32_t cs = CSet;
11029 int32_t copy=-1;
11030 int32_t copycnt=0;
11031
11032 int32_t tile_clicked=-1;
11033 int32_t t2;
11034
11035 bool masscopy;
11036
11037 int32_t w = 640;
11038 int32_t h = 480;
11039 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11040 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11041 int32_t screen_xofs=window_xofs+6;
11042 int32_t screen_yofs=window_yofs+25;
11043 int32_t panel_yofs=3;
11044 int32_t mul = 2;
11045 FONT *tfont = get_zc_font(font_lfont_l);
11046
11047 draw_combo_list_window();
11048 draw_combos(page,cs,true);
11049 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11050 anim_hw_screen();
11051 go_combos();
11052 position_mouse_z(0);
11053
11054 while(gui_mouse_b()) rest(1);
11055
11056 bool bdown=false;
11057 int otl = tile, otl2 = tile2;
11058
11059 do
11060 {
11061 HANDLE_CLOSE_ZQDLG();
11062 if(exiting_program) break;
11063 //rest(4);
11064
11065 if(mouse_z<0)
11066 {
11067 if(page<COMBO_PAGES-1)
11068 {
11069 ++page;
11070 tile=tile2=(page<<8)+(tile&0xFF);
11071 }
11072
11073 position_mouse_z(0);
11074 }
11075 else if(mouse_z>0)
11076 {
11077 if(page>0)
11078 {
11079 --page;
11080 tile=tile2=(page<<8)+(tile&0xFF);
11081 }
11082
11083 position_mouse_z(0);
11084 }
11085
11086 if(keypressed())
11087 {
11088 switch(readkey()>>8)
11089 {
11090 case KEY_ENTER_PAD:
11091 case KEY_ENTER:
11092 done=2;
11093 break;
11094
11095 case KEY_ESC:
11096 done=1;
11097 break;
11098
11099 case KEY_F1:
11100 onHelp();
11101 break;
11102
11103 case KEY_EQUALS:
11104 case KEY_PLUS_PAD:
11105 if(CHECK_CTRL_CMD)
11106 {
11107 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11108 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11109 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11110
11111 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11112 {
11113 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11114 0, NEWMAXTILES-1));
11115 }
11116
11117 setup_combo_animations();
11118 }
11119 else
11120 {
11121 cs = (cs<13) ? cs+1:0;
11122 }
11123
11124 break;
11125
11126 case KEY_MINUS:
11127 case KEY_MINUS_PAD:
11128 if(CHECK_CTRL_CMD)
11129 {
11130 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11131 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11132 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11133
11134 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11135 {
11136 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11137 0, NEWMAXTILES-1));
11138 }
11139
11140 setup_combo_animations();
11141 }
11142 else
11143 {
11144 cs = (cs>0) ? cs-1:13;
11145 }
11146
11147 break;
11148
11149 case KEY_UP:
11150 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11151 break;
11152
11153 case KEY_DOWN:
11154 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11155 break;
11156
11157 case KEY_LEFT:
11158 sel_combo(tile,tile2,-1,true);
11159 break;
11160
11161 case KEY_RIGHT:
11162 sel_combo(tile,tile2,1,true);
11163 break;
11164
11165 case KEY_PGUP:
11166 if(page>0)
11167 {
11168 --page;
11169 tile=tile2=(page<<8)+(tile&0xFF);
11170 }
11171 break;
11172
11173 case KEY_PGDN:
11174 if(page<COMBO_PAGES-1)
11175 {
11176 ++page;
11177 tile=tile2=(page<<8)+(tile&0xFF);
11178 }
11179 break;
11180
11181 case KEY_A:
11182 {
11183 tile=(page<<8);
11184 tile2=(page<<8)+(0xFF);
11185 }
11186 break;
11187
11188 case KEY_P:
11189 {
11190 if (auto num = call_get_num("Goto Page", (PreFillComboEditorPage?page:0), COMBO_PAGES-1))
11191 {
11192 page = *num;
11193 tile = tile2 = (page<<8)+(tile&0xFF);
11194 }
11195 }
11196 break;
11197
11198 case KEY_U:
11199 comeback_combos();
11200 break;
11201
11202 case KEY_E:
11203 go_combos();
11204 edit_combo(tile,false,cs);
11205 setup_combo_animations();
11206 setup_combo_animations2();
11207 break;
11208
11209 case KEY_C:
11210 go_combos();
11211 copy=zc_min(tile,tile2);
11212 copycnt=abs(tile-tile2)+1;
11213 break;
11214
11215 case KEY_H:
11216 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11217 {
11218 combobuf[i].flip^=1;
11219 byte w2=combobuf[i].walk;
11220 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11221 w2=combobuf[i].csets;
11222 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11223 }
11224
11225 mark_save_dirty();
11226 break;
11227
11228 case KEY_M:
11229 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11230 {
11231 move_combos(tile,tile2,copy,copycnt);
11232 mark_save_dirty();
11233 }
11234 break;
11235
11236 case KEY_S:
11237 tile=tile2=zc_min(tile,tile2);
11238
11239 if(copy>=0 && tile!=copy)
11240 {
11241 go_combos();
11242
11243 for(int32_t i=0; i<copycnt; i++)
11244 {
11245 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11246 }
11247
11248 mark_save_dirty();
11249 setup_combo_animations();
11250 setup_combo_animations2();
11251 }
11252
11253 copy=-1;
11254 break;
11255
11256 case KEY_V:
11257 if((CHECK_CTRL_CMD) && copy != -1)
11258 {
11259 if(advpaste(tile, tile2, copy))
11260 {
11261 mark_save_dirty();
11262 copy=-1;
11263 }
11264
11265 break;
11266 }
11267
11268 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11269
11270 if(copy==-1)
11271 {
11272 go_combos();
11273
11274 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11275 {
11276 combobuf[i].flip^=2;
11277 byte w2=combobuf[i].walk;
11278 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11279 w2=combobuf[i].csets;
11280 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11281 }
11282
11283 mark_save_dirty();
11284 }
11285 else
11286 {
11287 go_combos();
11288 copy_combos(tile,tile2,copy,copycnt,masscopy);
11289 setup_combo_animations();
11290 setup_combo_animations2();
11291 mark_save_dirty();
11292 }
11293 break;
11294 case KEY_R:
11295 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11296 {
11297 combobuf[i].flip = rotate_value(combobuf[i].flip);
11298 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11299 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11300 }
11301
11302 mark_save_dirty();
11303 break;
11304
11305 case KEY_I:
11306 {
11307 // rev.1509; Can now insert/remove all selected combos
11308 int32_t z=tile;
11309 int32_t numSelected = abs(tile-tile2) + 1;
11310 tile=zc_min(tile,tile2);
11311 tile2=MAXCOMBOS;
11312 copy = tile + numSelected; // copy=tile+1;
11313 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11314
11315 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11316 {
11317 char buf[64];
11318
11319 if(numSelected>1)
11320 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11321 else
11322 sprintf(buf,"Remove combo %d?",tile);
11323
11324 if (alert_confirm("Confirm Remove",fmt::format("{}\nThis will offset all of the combos that follow!",buf)))
11325 {
11326 move_combos(tile,tile2,copy, copycnt);
11327 //don't allow the user to undo; quest combo references are incorrect -DD
11328 go_combos();
11329 mark_save_dirty();
11330 }
11331 }
11332 else
11333 {
11334 char buf[64];
11335
11336 if(numSelected>1)
11337 sprintf(buf,"Insert %d blank combos?",numSelected);
11338 else
11339 sprintf(buf,"Insert a blank combo?");
11340
11341 if (alert_confirm("Confirm Insert",fmt::format("{}\nThis will offset all of the combos that follow!", buf)))
11342 {
11343 move_combos(copy,tile2,tile, copycnt);
11344 go_combos();
11345 mark_save_dirty();
11346 }
11347 }
11348
11349 copy=-1;
11350 tile2=tile=z;
11351 }
11352 break;
11353
11354 case KEY_DEL:
11355 {
11356 char buf[40];
11357
11358 if(tile==tile2)
11359 {
11360 sprintf(buf,"Delete combo %d?",tile);
11361 }
11362 else
11363 {
11364 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11365 }
11366
11367 if(alert_confirm("Confirm Delete",buf))
11368 {
11369 go_combos();
11370
11371 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11372 {
11373 clear_combo(i);
11374 }
11375
11376 tile=tile2=zc_min(tile,tile2);
11377 mark_save_dirty();
11378 setup_combo_animations();
11379 setup_combo_animations2();
11380 }
11381 }
11382 break;
11383 }
11384
11385 clear_keybuf();
11386 }
11387
11388 if(gui_mouse_b()&1)
11389 {
11390 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11391 {
11392 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11393 {
11394 done=1;
11395 }
11396 }
11397
11398 int32_t x=gui_mouse_x()-screen_xofs;
11399 int32_t y=gui_mouse_y()-screen_yofs;
11400
11401 if(y>=0 && y<(208*mul))
11402 {
11403 x=zc_min(zc_max(x,0),(320*mul)-1);
11404 int32_t t;
11405
11406 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11407
11408 bound(t,0,255);
11409 t+=page<<8;
11410
11411 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11412 {
11413 tile2=t;
11414 }
11415 else
11416 {
11417 tile=tile2=t;
11418 }
11419
11420 if(tile_clicked!=t)
11421 {
11422 dclick_status=DCLICK_NOT;
11423 }
11424 else if(dclick_status == DCLICK_AGAIN)
11425 {
11426 while(gui_mouse_b()) rest(1);
11427
11428 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11429
11430 bound(t2,0,255);
11431 t2+=page<<8;
11432
11433 if(t2!=t)
11434 {
11435 dclick_status=DCLICK_NOT;
11436 }
11437 else
11438 {
11439 go_combos();
11440 edit_combo(tile,false,cs);
11441 setup_combo_animations();
11442 setup_combo_animations2();
11443 }
11444 }
11445
11446 tile_clicked=t;
11447 }
11448 else if(x>(300*mul) && !bdown)
11449 {
11450 if(y<(224*mul)+panel_yofs && page>0)
11451 {
11452 --page;
11453 }
11454
11455 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11456 {
11457 ++page;
11458 }
11459
11460 bdown=true;
11461 }
11462
11463 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11464 {
11465 FONT *tf = font;
11466 font = tfont;
11467
11468 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11469 {
11470 font = tf;
11471 edit_combo(tile,false,cs);
11472 }
11473
11474 font = tf;
11475 }
11476 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11477 {
11478 FONT *tf = font;
11479 font = tfont;
11480
11481 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11482 {
11483 done=1;
11484 }
11485
11486 font = tf;
11487 }
11488 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11489 {
11490 FONT *tf = font;
11491 font = tfont;
11492
11493 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11494 combopage_animate = combopage_animate ? 0 : 1;
11495 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11496
11497 font = tf;
11498 }
11499
11500 bdown=true;
11501 }
11502
11503 bool r_click = false;
11504 bool force_draw_select = false;
11505 if(gui_mouse_b()&2 && !bdown)
11506 {
11507 int32_t x=gui_mouse_x()-screen_xofs;
11508 int32_t y=gui_mouse_y()-screen_yofs;
11509
11510 if(y>=0 && y<(208*mul))
11511 {
11512 x=zc_min(zc_max(x,0),(320*mul)-1);
11513 int32_t t;
11514
11515 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11516
11517 bound(t,0,255);
11518 t+=page<<8;
11519
11520 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11521 {
11522 tile=tile2=t;
11523 }
11524 }
11525
11526 bdown = r_click = true;
11527 force_draw_select = true;
11528 }
11529
11530 REDRAW:
11531
11532 if(gui_mouse_b()==0)
11533 bdown=false;
11534
11535 if(otl != tile || otl2 != tile2)
11536 {
11537 otl = tile;
11538 otl2 = tile2;
11539 }
11540
11541 // if(true) // redraw every frame now. Eyeball combos need to animate regardless, and cursor blinks every 8 frames anyway.
11542 {
11543 draw_combos(page,cs,true);
11544 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11545 if(force_draw_select || (framecnt&8))
11546 {
11547 int32_t x,y;
11548
11549 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11550 {
11551 if((i>>8)==page)
11552 {
11553 int32_t t=i&255;
11554
11555 x=((t&3) + ((t/52)<<2)) << 5;
11556 y=((t%52)>>2) << 5;
11557
11558 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11559 }
11560 }
11561 }
11562 }
11563 anim_hw_screen();
11564
11565 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11566 if(r_click)
11567 {
11568 NewMenu rcmenu
11569 {
11570 { "Copy", [&]()
11571 {
11572 go_combos();
11573 copy=zc_min(tile,tile2);
11574 copycnt=abs(tile-tile2)+1;
11575 } },
11576 { "Paste", [&]()
11577 {
11578 if((CHECK_CTRL_CMD))
11579 {
11580 if(advpaste(tile, tile2, copy))
11581 {
11582 mark_save_dirty();
11583 copy=-1;
11584 }
11585 return;
11586 }
11587
11588 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11589
11590 go_combos();
11591 copy_combos(tile,tile2,copy,copycnt,masscopy);
11592 setup_combo_animations();
11593 setup_combo_animations2();
11594 mark_save_dirty();
11595 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11596 { "Adv. Paste", [&]()
11597 {
11598 if(advpaste(tile, tile2, copy))
11599 {
11600 mark_save_dirty();
11601 copy=-1;
11602 }
11603 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11604 { "Move", [&]()
11605 {
11606 if(copy!=zc_min(tile,tile2))
11607 {
11608 move_combos(tile,tile2,copy,copycnt);
11609 mark_save_dirty();
11610 setup_combo_animations();
11611 setup_combo_animations2();
11612 }
11613 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11614 { "Swap", [&]()
11615 {
11616 tile=tile2=zc_min(tile,tile2);
11617
11618 if(tile!=copy)
11619 {
11620 go_combos();
11621
11622 for(int32_t i=0; i<copycnt; i++)
11623 {
11624 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11625 }
11626
11627 mark_save_dirty();
11628 setup_combo_animations();
11629 setup_combo_animations2();
11630 }
11631 copy=-1;
11632 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11633 { "Delete", [&]()
11634 {
11635 string msg;
11636
11637 if(tile==tile2)
11638 msg = fmt::format("Delete combo {}?",tile);
11639 else
11640 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11641 if (alert_confirm("Confirm Delete",msg))
11642 {
11643 go_combos();
11644
11645 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11646 clear_combo(i);
11647
11648 tile=tile2=zc_min(tile,tile2);
11649 mark_save_dirty();
11650 }
11651 } },
11652 {},
11653 { "Edit", [&]()
11654 {
11655 go_combos();
11656 edit_combo(tile,false,cs);
11657 } },
11658 { "Insert", [&]()
11659 {
11660 int z = tile;
11661 int count = abs(tile-tile2)+1;
11662 tile = zc_min(tile,tile2);
11663 tile2 = MAXCOMBOS;
11664 copy = tile+count;
11665 copycnt = MAXCOMBOS-tile-count;
11666
11667 string msg;
11668
11669 if(count>1)
11670 msg = fmt::format("Insert combos {} - {}?"
11671 " This will offset all of the combos that follow!",tile, copy-1);
11672 else
11673 msg = fmt::format("Insert combo {}?"
11674 " This will offset all of the combos that follow!",tile);
11675
11676 if (alert_confirm("Confirm Insert",msg))
11677 move_combos(copy, tile2, tile, copycnt);
11678 else return;
11679
11680 copy = -1;
11681 tile2 = tile = z;
11682
11683 //don't allow the user to undo; quest combo references are incorrect -DD
11684 go_combos();
11685 mark_save_dirty();
11686 } },
11687 { "Remove", [&]()
11688 {
11689 int z = tile;
11690 int count = abs(tile-tile2)+1;
11691 tile = zc_min(tile,tile2);
11692 tile2 = MAXCOMBOS;
11693 copy = tile+count;
11694 copycnt = MAXCOMBOS-tile-count;
11695
11696 string msg;
11697
11698 if(count>1)
11699 msg = fmt::format("Remove combos {} - {}?"
11700 " This will offset all of the combos that follow!",tile, copy-1);
11701 else
11702 msg = fmt::format("Remove combo {}?"
11703 " This will offset all of the combos that follow!",tile);
11704
11705 if (alert_confirm("Confirm Remove", msg))
11706 move_combos(tile, tile2, copy, copycnt);
11707 else return;
11708
11709 copy = -1;
11710 tile2 = tile = z;
11711
11712 //don't allow the user to undo; quest combo references are incorrect -DD
11713 go_combos();
11714 mark_save_dirty();
11715 } },
11716 {},
11717 { "Locations", [&]()
11718 {
11719 int32_t z = Combo;
11720 Combo = tile;
11721 onComboLocationReport();
11722 Combo = z;
11723 } },
11724 };
11725 rcmenu.pop(window_mouse_x(),window_mouse_y());
11726 r_click = false;
11727 goto REDRAW;
11728 }
11729
11730 }
11731 while(!done);
11732
11733 while(gui_mouse_b()) rest(1);
11734 setup_combo_animations();
11735 setup_combo_animations2();
11736 _selected_combo = tile;
11737 _selected_cset = cs;
11738 popup_zqdialog_end();
11739 return done-1;
11740 }
11741
11742 int32_t onCombos()
11743 {
11744 combo_screen(-1,-1);
11745 refresh(rALL);
11746 return D_O_K;
11747 }
11748
11749 12 static newcombo curr_combo;
11750 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11751 {
11752 //these are here to bypass compiler warnings about unused arguments
11753 c=c;
11754
11755 if(msg==MSG_DRAW)
11756 {
11757 FONT *f = get_zc_font(font_lfont_l);
11758 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
11759 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
11760 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
11761 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
11762 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
11763 }
11764
11765 return D_O_K;
11766 }
11767
11768 bool call_combo_editor(int32_t);
11769 bool edit_combo(int32_t c,bool freshen,int32_t cs)
11770 {
11771 FONT* ofont = font;
11772 //CSet = cs;
11773 reset_combo_animations();
11774 reset_combo_animations2();
11775 bool edited = call_combo_editor(c);
11776 font = ofont;
11777
11778 if(freshen)
11779 {
11780 refresh(rALL);
11781 }
11782
11783 setup_combo_animations();
11784 setup_combo_animations2();
11785
11786 return edited;
11787 }
11788
11789 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
11790 {
11791 switch(msg)
11792 {
11793 case MSG_CLICK:
11794 {
11795 int32_t cs = d->d2;
11796 int32_t flip = 0;
11797
11798 if(select_tile(d->d1,flip,1,cs,true))
11799 {
11800 int32_t ok=1;
11801
11802 if(newtilebuf[d->d1].format==tf8Bit)
11803 displayinfo("Warning", "You have selected an 8-bit tile."
11804 "\nIt will not be drawn correctly on the file select screen.");
11805
11806 return D_REDRAW;
11807 }
11808 }
11809 break;
11810
11811 case MSG_DRAW:
11812 d->w = 32+4;
11813 d->h = 32+4;
11814
11815 BITMAP *buf = create_bitmap_ex(8,16,16);
11816 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
11817
11818 if(buf && bigbmp)
11819 {
11820 clear_bitmap(buf);
11821 overtile16(buf,d->d1,0,0,d->fg,0);
11822 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
11823 destroy_bitmap(buf);
11824 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
11825 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
11826 destroy_bitmap(bigbmp);
11827 }
11828
11829 break;
11830 }
11831
11832 return D_O_K;
11833 }
11834
11835 static DIALOG icon_dlg[] =
11836 {
11837 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
11838 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
11839 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
11840 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
11841 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
11842 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
11843 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
11844 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
11845 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
11846 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
11847 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
11848 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
11849 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
11850 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
11851 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
11852 };
11853
11854 int32_t onIcons()
11855 {
11856 PALETTE pal;
11857 memcpy(pal,RAMpal,sizeof(RAMpal));
11858 icon_dlg[0].dp2=get_zc_font(font_lfont);
11859
11860 for(int32_t i=0; i<4; i++)
11861 {
11862 icon_dlg[i+2].d1 = QMisc.icons[i];
11863 icon_dlg[i+2].fg = i+6;
11864 load_cset(pal, i+6, pSprite(i+spICON1));
11865 }
11866
11867 zc_set_palette(pal);
11868
11869 large_dialog(icon_dlg);
11870
11871 int32_t ret = do_zqdialog(icon_dlg,7);
11872
11873 if(ret==6)
11874 {
11875 for(int32_t i=0; i<4; i++)
11876 {
11877 if(QMisc.icons[i] != icon_dlg[i+2].d1)
11878 {
11879 QMisc.icons[i] = icon_dlg[i+2].d1;
11880 mark_save_dirty();
11881 }
11882 }
11883 }
11884
11885 zc_set_palette(RAMpal);
11886 return D_O_K;
11887 }
11888
11889 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
11890 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
11891 {
11892 if(msg == MSG_DRAW)
11893 {
11894 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
11895 }
11896
11897 return D_O_K;
11898 }
11899
11900 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
11901 {
11902 switch(msg)
11903 {
11904 case MSG_CLICK:
11905 {
11906 if((d->flags&D_NOCLICK))
11907 break;
11908
11909 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
11910 int32_t combo2;
11911 int32_t cs;
11912
11913 if(CHECK_ALT) //place selected cmb/cs
11914 {
11915 if(gui_mouse_b()&1)
11916 {
11917 if(!CHECK_SHIFT)
11918 d->d1 = Combo;
11919 d->fg = CSet;
11920 }
11921
11922 return ret|D_REDRAW;
11923 }
11924 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
11925 {
11926 d->d1=0;
11927 d->fg=0;
11928 return ret|D_REDRAW;
11929 }
11930 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
11931 {
11932 combo2=d->d1;
11933 cs=d->fg;
11934
11935 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
11936 {
11937 d->d1=combo2;
11938 d->fg=cs;
11939 }
11940
11941 return ret|D_REDRAW;
11942 }
11943 else return ret|D_REDRAWME;
11944 }
11945 break;
11946
11947 case MSG_DRAW:
11948 {
11949 d->w = 32;
11950 d->h = 32;
11951
11952 BITMAP *buf = create_bitmap_ex(8,16,16);
11953 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
11954
11955 if(buf && bigbmp)
11956 {
11957 clear_bitmap(buf);
11958
11959 if(d->d1==-1) // Display curr_combo instead of combobuf
11960 {
11961 newcombo hold = combobuf[0];
11962 combobuf[0] = curr_combo;
11963 putcombo(buf,0,0,0,d->fg);
11964 combobuf[0] = hold;
11965 }
11966 else if(d->d1)
11967 {
11968 putcombo(buf,0,0,d->d1,d->fg);
11969 }
11970
11971 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
11972 destroy_bitmap(buf);
11973 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
11974 destroy_bitmap(bigbmp);
11975 }
11976 }
11977 break;
11978 }
11979 return D_O_K;
11980 }
11981
11982 // Hey, let's have a few hundred more lines of code, why not.
11983
11984 #define MR_4BIT 0
11985 #define MR_8BIT 1
11986
11987 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
11988 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
11989 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
11990
11991 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
11992 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
11993
11994 static int32_t massRecolorDraggedColor=-1;
11995 static int32_t massRecolorCSet;
11996 static bool massRecolorIgnoreBlank=true;
11997 static byte massRecolorType=MR_4BIT;
11998
11999 // Shows the sets of colors to replace from/to.
12000 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12001 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12002 #define D_CSET D_USER
12003 #define D_SETTABLE (D_USER<<1)
12004 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12005 {
12006 BITMAP* bmp=screen;
12007 int32_t colorWidth=(d->w-4)/16;
12008 byte* colors=static_cast<byte*>(d->dp);
12009
12010 switch(msg)
12011 {
12012 case MSG_DRAW:
12013 {
12014 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12015
12016 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12017 for(int32_t c=0; c<16; c++)
12018 {
12019 rectfill(bmp,
12020 d->x+2+c*colorWidth, d->y+2,
12021 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12022 baseColor+colors[c]);
12023 }
12024 }
12025 break;
12026
12027 case MSG_LPRESS:
12028 {
12029 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12030
12031 if(x >= 0 && x < 16) //sanity check!
12032 {
12033 massRecolorDraggedColor=colors[x];
12034 }
12035 }
12036 break;
12037
12038 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12039 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12040 {
12041 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12042 if(x >= 0 && x < 16) //sanity check!
12043 {
12044 colors[x]=massRecolorDraggedColor;
12045 d->flags|=D_DIRTY;
12046 }
12047 }
12048 massRecolorDraggedColor=-1;
12049 break;
12050 }
12051
12052 return D_O_K;
12053 }
12054
12055 // Used for the full palette in 8-bit mode.
12056 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12057 {
12058 BITMAP* bmp=screen;
12059 int colorWidth=(d->w-4)/16;
12060 d->h = 4+(colorWidth*14);
12061 int colorHeight=colorWidth;
12062
12063 switch(msg)
12064 {
12065 case MSG_DRAW:
12066 {
12067 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12068 for(int cset=0; cset<=13; cset++)
12069 {
12070 for(int color=0; color<16; color++)
12071 {
12072 rectfill(bmp,
12073 d->x+2+color*colorWidth,
12074 d->y+2+cset*colorHeight,
12075 d->x+2+((color+1)*colorWidth)-1,
12076 d->y+2+((cset+1)*colorHeight)-1,
12077 cset*16+color);
12078 }
12079 }
12080 }
12081 break;
12082
12083 case MSG_LPRESS:
12084 {
12085 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12086 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12087 massRecolorDraggedColor=cset*16+color;
12088 }
12089 break;
12090 }
12091
12092 return D_O_K;
12093 }
12094
12095 static DIALOG recolor_4bit_dlg[] =
12096 {
12097 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12098 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12099
12100 // 1
12101 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12102 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12103 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12104 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12105
12106 // 5
12107 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12108 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12109 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12110 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12111 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12112 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12113 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12114 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12115 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12116 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12117 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12118 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12119 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12120 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12121 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12122
12123 // 20
12124 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12125 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12126 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12127 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12128 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12129
12130 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12131 };
12132
12133 #define MR4_SRC_COLORS 2
12134 #define MR4_DEST_COLORS 4
12135 #define MR4_8BIT_EFFECT_START 6
12136 #define MR4_IGNORE_BLANK 20
12137 #define MR4_RESET 21
12138 #define MR4_SWITCH 22
12139 #define MR4_OK 23
12140 #define MR4_CANCEL 24
12141
12142 static DIALOG recolor_8bit_dlg[] =
12143 {
12144 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12145 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12146
12147 // 1
12148 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12149 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12150 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12151 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12152 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12153
12154 // 6
12155 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12156 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12157 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12158 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12159 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12160
12161 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12162 };
12163
12164 #define MR8_SRC_COLORS 2
12165 #define MR8_DEST_COLORS 4
12166 #define MR8_PALETTE 5
12167 #define MR8_IGNORE_BLANK 6
12168 #define MR8_RESET 7
12169 #define MR8_SWITCH 8
12170 #define MR8_OK 9
12171 #define MR8_CANCEL 10
12172
12173 static void massRecolorInit(int32_t cset)
12174 {
12175 massRecolorDraggedColor=-1;
12176 massRecolorCSet=cset;
12177
12178 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12179 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12180
12181 for(int32_t i=0; i<=13; i++)
12182 {
12183 if((massRecolor8BitCSets&(1<<i))!=0)
12184 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12185 else
12186 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12187 }
12188
12189 if(massRecolorIgnoreBlank)
12190 {
12191 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12192 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12193 }
12194 else
12195 {
12196 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12197 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12198 }
12199
12200 large_dialog(recolor_4bit_dlg);
12201 large_dialog(recolor_8bit_dlg);
12202
12203 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12204 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12205 {
12206 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12207 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12208 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12209 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12210
12211 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12212 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12213 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12214 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12215 recolor_8bit_dlg[MR8_PALETTE].x++;
12216 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12217 recolor_8bit_dlg[MR8_PALETTE].y++;
12218 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12219 }
12220 }
12221
12222 static void massRecolorApplyChanges()
12223 {
12224 massRecolor8BitCSets=0;
12225 for(int32_t i=0; i<=13; i++)
12226 {
12227 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12228 massRecolor8BitCSets|=1<<i;
12229 }
12230
12231 if(massRecolorType==MR_4BIT)
12232 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12233 else
12234 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12235 }
12236
12237 static bool massRecolorSetup(int32_t cset)
12238 {
12239 massRecolorInit(cset);
12240
12241 // Remember the current colors in case the user cancels.
12242 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12243 for(int32_t i=0; i<16; i++)
12244 {
12245 oldDest4Bit[i]=massRecolorDest4Bit[i];
12246 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12247 oldDest8Bit[i]=massRecolorDest8Bit[i];
12248 }
12249
12250 byte type=massRecolorType;
12251 int32_t ret;
12252 do
12253 {
12254 HANDLE_CLOSE_ZQDLG();
12255 if(exiting_program) break;
12256 if(type==MR_4BIT)
12257 {
12258 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12259 if(ret==MR4_SWITCH)
12260 type=MR_8BIT;
12261 }
12262 else
12263 {
12264 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12265 if(ret==MR8_SWITCH)
12266 type=MR_4BIT;
12267 }
12268 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12269
12270 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12271 {
12272 for(int32_t i=0; i<16; i++)
12273 {
12274 massRecolorDest4Bit[i]=oldDest4Bit[i];
12275 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12276 massRecolorDest8Bit[i]=oldDest8Bit[i];
12277 }
12278 return false;
12279 }
12280
12281 // OK
12282 massRecolorType=type;
12283 massRecolorApplyChanges();
12284 return true;
12285 }
12286
12287 static void massRecolorApply4Bit(int32_t tile)
12288 {
12289 byte buf[256];
12290 unpack_tile(newtilebuf, tile, 0, true);
12291
12292 if(newtilebuf[tile].format==tf4Bit)
12293 {
12294 for(int32_t i=0; i<256; i++)
12295 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12296 }
12297 else // 8-bit
12298 {
12299 for(int32_t i=0; i<256; i++)
12300 {
12301 word cset=unpackbuf[i]>>4;
12302 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12303 {
12304 word color=unpackbuf[i]&15;
12305 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12306 }
12307 else
12308 buf[i]=unpackbuf[i];
12309 }
12310 }
12311
12312 pack_tile(newtilebuf, buf, tile);
12313 }
12314
12315 static void massRecolorApply8Bit(int32_t tile)
12316 {
12317 byte buf[256];
12318 unpack_tile(newtilebuf, tile, 0, true);
12319
12320 for(int32_t i=0; i<256; i++)
12321 {
12322 byte color=unpackbuf[i];
12323 for(int32_t j=0; j<16; j++)
12324 {
12325 if(massRecolorSrc8Bit[j]==color)
12326 {
12327 color=massRecolorDest8Bit[j];
12328 break;
12329 }
12330 }
12331 buf[i]=color;
12332 }
12333
12334 pack_tile(newtilebuf, buf, tile);
12335 }
12336
12337 static void massRecolorApply(int32_t tile)
12338 {
12339 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12340 return;
12341
12342 if(massRecolorType==MR_4BIT)
12343 massRecolorApply4Bit(tile);
12344 else // 8-bit
12345 {
12346 if(newtilebuf[tile].format==tf4Bit)
12347 return;
12348 massRecolorApply8Bit(tile);
12349 }
12350 }
12351
12352 static void massRecolorReset4Bit()
12353 {
12354 for(int32_t i=0; i<16; i++)
12355 massRecolorDest4Bit[i]=i;
12356 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12357 }
12358
12359 static void massRecolorReset8Bit()
12360 {
12361 for(int32_t i=0; i<16; i++)
12362 {
12363 massRecolorSrc8Bit[i]=0;
12364 massRecolorDest8Bit[i]=0;
12365 }
12366
12367 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12368 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12369 }
12370
12371 1 void center_zq_tiles_dialogs()
12372 {
12373 1 jwin_center_dialog(create_relational_tiles_dlg);
12374 1 jwin_center_dialog(icon_dlg);
12375 1 jwin_center_dialog(leech_dlg);
12376 1 jwin_center_dialog(move_textbox_list_dlg);
12377 1 jwin_center_dialog(recolor_4bit_dlg);
12378 1 jwin_center_dialog(recolor_8bit_dlg);
12379 1 }
12380
12381 //.ZCOMBO
12382
12383 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12384 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12385
12386 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12387 dword section_version, int32_t index, int32_t count)
12388 {
12389 byte tempbyte;
12390 newcombo temp_combo;
12391 for ( int32_t tilect = 0; tilect < count; tilect++ )
12392 {
12393 int32_t temp_trigflags[3] = {0};
12394 temp_combo.clear();
12395 combo_trigger& temp_trigger = temp_combo.triggers.emplace_back();
12396 if(!p_igetw(&temp_combo.tile,f))
12397 {
12398 return 0;
12399 }
12400 temp_combo.o_tile = temp_combo.tile;
12401
12402 if(!p_getc(&temp_combo.flip,f))
12403 {
12404 return 0;
12405 }
12406
12407 if(!p_getc(&temp_combo.walk,f))
12408 {
12409 return 0;
12410 }
12411
12412 if(!p_getc(&temp_combo.type,f))
12413 {
12414 return 0;
12415 }
12416
12417 if(!p_getc(&temp_combo.csets,f))
12418 {
12419 return 0;
12420 }
12421
12422 if(!p_getc(&temp_combo.frames,f))
12423 {
12424 return 0;
12425 }
12426
12427 if(!p_getc(&temp_combo.speed,f))
12428 {
12429 return 0;
12430 }
12431
12432 if(!p_igetw(&temp_combo.nextcombo,f))
12433 {
12434 return 0;
12435 }
12436
12437 if(!p_getc(&temp_combo.nextcset,f))
12438 {
12439 return 0;
12440 }
12441
12442 if(!p_getc(&temp_combo.flag,f))
12443 {
12444 return 0;
12445 }
12446
12447 if(!p_getc(&temp_combo.skipanim,f))
12448 {
12449 return 0;
12450 }
12451
12452 if(!p_igetw(&temp_combo.nexttimer,f))
12453 {
12454 return 0;
12455 }
12456
12457 if(!p_getc(&temp_combo.skipanimy,f))
12458 {
12459 return 0;
12460 }
12461
12462 if(!p_getc(&temp_combo.animflags,f))
12463 {
12464 return 0;
12465 }
12466
12467 //2.55 starts here
12468 if ( zversion >= 0x255 )
12469 {
12470 if ( section_version >= 12 )
12471 {
12472 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12473 {
12474 if(!p_igetl(&temp_combo.attributes[q],f))
12475 {
12476 return 0;
12477 }
12478 }
12479 if(!p_igetl(&temp_combo.usrflags,f))
12480 {
12481 return 0;
12482 }
12483 for ( int32_t q = 0; q < 3; q++ )
12484 {
12485 if(!p_igetl(&temp_trigflags[q],f))
12486 return 0;
12487 }
12488
12489 if(!p_igetl(&temp_trigger.triggerlevel,f))
12490 {
12491 return 0;
12492 }
12493 if(section_version >= 22)
12494 {
12495 if(!p_getc(&temp_trigger.triggerbtn,f))
12496 {
12497 return 0;
12498 }
12499 }
12500 if(section_version < 23)
12501 {
12502 switch(temp_combo.type) // TRIGFLAG_CMBTYPEFX now required for combotype-specific effects
12503 {
12504 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12505 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12506 case cTRIGGERGENERIC: case cCSWITCH:
12507 temp_trigflags[TRIGFLAG_CMBTYPEFX/32] |= 1 << (TRIGFLAG_CMBTYPEFX%32);
12508 }
12509 }
12510 if(section_version >= 24)
12511 {
12512 if(!p_getc(&temp_trigger.triggeritem,f))
12513 {
12514 return 0;
12515 }
12516 if(!p_getc(&tempbyte, f))
12517 return 0;
12518 temp_trigger.trigtimer = tempbyte;
12519 }
12520 if(section_version >= 25)
12521 {
12522 if(!p_getc(&temp_trigger.trigsfx,f))
12523 {
12524 return 0;
12525 }
12526 }
12527 else
12528 {
12529 switch(temp_combo.type)
12530 {
12531 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12532 if(!(temp_combo.usrflags & cflag3))
12533 temp_combo.attribytes[3] = WAV_DOOR;
12534 temp_combo.usrflags &= ~cflag3;
12535 break;
12536 }
12537 }
12538 if(section_version < 26)
12539 {
12540 if(temp_combo.type == cARMOS)
12541 {
12542 if(temp_combo.usrflags & cflag1)
12543 temp_combo.usrflags |= cflag3;
12544 }
12545 }
12546 if(section_version >= 27)
12547 {
12548 if(!p_igetl(&temp_trigger.trigchange,f))
12549 {
12550 return qe_invalid;
12551 }
12552 }
12553 else
12554 {
12555 if(temp_trigflags[0] & 0x00040000) //'next'
12556 temp_trigger.trigchange = 1;
12557 else if(temp_trigflags[0] & 0x00080000) //'prev'
12558 temp_trigger.trigchange = -1;
12559 else temp_trigger.trigchange = 0;
12560 temp_trigflags[0] &= ~(0x00040000|0x00080000);
12561 }
12562 if(section_version >= 29)
12563 {
12564 if(!p_igetw(&temp_trigger.trigprox,f))
12565 {
12566 return qe_invalid;
12567 }
12568 if(!p_getc(&tempbyte,f))
12569 return qe_invalid;
12570 temp_trigger.trigctr = tempbyte;
12571 if(!p_igetl(&temp_trigger.trigctramnt,f))
12572 {
12573 return qe_invalid;
12574 }
12575 }
12576 else
12577 {
12578 temp_trigger.trigprox = 0;
12579 temp_trigger.trigctr = 0;
12580 temp_trigger.trigctramnt = 0;
12581 }
12582 if(section_version >= 30)
12583 {
12584 if(!p_getc(&temp_trigger.triglbeam,f))
12585 {
12586 return qe_invalid;
12587 }
12588 }
12589 else temp_trigger.triglbeam = 0;
12590 if(section_version >= 31)
12591 {
12592 if(!p_getc(&temp_trigger.trigcschange,f))
12593 {
12594 return qe_invalid;
12595 }
12596 if(!p_igetw(&temp_trigger.spawnitem,f))
12597 {
12598 return qe_invalid;
12599 }
12600 if(!p_igetw(&temp_trigger.spawnenemy,f))
12601 {
12602 return qe_invalid;
12603 }
12604 if(!p_getc(&temp_trigger.exstate,f))
12605 {
12606 return qe_invalid;
12607 }
12608 if(!p_igetl(&temp_trigger.spawnip,f))
12609 {
12610 return qe_invalid;
12611 }
12612 if(!p_getc(&temp_trigger.trigcopycat,f))
12613 {
12614 return qe_invalid;
12615 }
12616 }
12617 else
12618 {
12619 temp_trigger.trigcschange = 0;
12620 temp_trigger.spawnitem = 0;
12621 temp_trigger.spawnenemy = 0;
12622 temp_trigger.exstate = -1;
12623 temp_trigger.spawnip = 0;
12624 temp_trigger.trigcopycat = 0;
12625 }
12626 if(section_version >= 32)
12627 {
12628 if(!p_getc(&temp_trigger.trigcooldown,f))
12629 {
12630 return qe_invalid;
12631 }
12632 }
12633 else
12634 {
12635 temp_trigger.trigcooldown = 0;
12636 }
12637 char label[12];
12638 label[11] = '\0';
12639 for ( int32_t q = 0; q < 11; q++ )
12640 {
12641 if(!p_getc(&label[q],f))
12642 {
12643 return 0;
12644 }
12645 }
12646 temp_combo.label = label;
12647 }
12648 if ( section_version >= 13 )
12649 {
12650 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12651 {
12652 if(!p_getc(&temp_combo.attribytes[q],f))
12653 {
12654 return 0;
12655 }
12656 }
12657
12658 }
12659 }
12660
12661 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12662 {
12663 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12664 {
12665 combobuf[index+(tilect)] = temp_combo;
12666 }
12667 }
12668
12669 temp_trigger.trigger_flags.clear();
12670 for(size_t q = 0; q < 32*3; ++q)
12671 {
12672 auto ind = q/32;
12673 auto bit = 1<<(q%32);
12674 if(temp_trigflags[ind] & bit)
12675 temp_trigger.trigger_flags.set(q, true);
12676 }
12677 }
12678
12679 return 1;
12680 }
12681
12682 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12683 {
12684 dword section_version=0;
12685 int32_t zversion = 0;
12686 int32_t zbuild = 0;
12687
12688 if(!p_igetl(&zversion,f))
12689 {
12690 return 0;
12691 }
12692 if(!p_igetl(&zbuild,f))
12693 {
12694 return 0;
12695 }
12696 if(!p_igetw(&section_version,f))
12697 {
12698 return 0;
12699 }
12700 if(!read_deprecated_section_cversion(f))
12701 {
12702 return 0;
12703 }
12704
12705 if ( zversion > ZELDA_VERSION )
12706 {
12707 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12708 return 0;
12709 }
12710
12711 else if ( ( section_version > V_COMBOS ))
12712 {
12713 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d)\n", section_version);
12714 return 0;
12715
12716 }
12717 else
12718 {
12719 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12720 }
12721
12722 int32_t index = 0;
12723 int32_t count = 0;
12724
12725 //tile id
12726 if(!p_igetl(&index,f))
12727 {
12728 return 0;
12729 }
12730 if(start > -1) index = start;
12731
12732 //tile count
12733 if(!p_igetl(&count,f))
12734 {
12735 return 0;
12736 }
12737 reset_combo_animations();
12738 reset_combo_animations2();
12739
12740 if(section_version < 33)
12741 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,index,count);
12742
12743 newcombo temp_combo;
12744 size_t end = index+count;
12745 for ( size_t q = index; q < end; q++ )
12746 {
12747 auto ret = readcombo_loop(f,section_version,temp_combo);
12748 if(ret) return 0;
12749
12750 if ( !(skip && q-1 < skip) )
12751 {
12752 if ( !nooverwrite || combobuf[q].is_blank() )
12753 {
12754 combobuf[q] = temp_combo;
12755 }
12756 }
12757 }
12758
12759 return 1;
12760 }
12761 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
12762 {
12763 return readcombofile(f,skip,nooverwrite,start);
12764 }
12765 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
12766 {
12767 dword section_version=V_COMBOS;
12768 int32_t zversion = ZELDA_VERSION;
12769 int32_t zbuild = VERSION_BUILD;
12770
12771 if(!p_iputl(zversion,f))
12772 {
12773 return 0;
12774 }
12775 if(!p_iputl(zbuild,f))
12776 {
12777 return 0;
12778 }
12779 if(!p_iputw(section_version,f))
12780 {
12781 return 0;
12782 }
12783
12784 if(!write_deprecated_section_cversion(section_version,f))
12785 {
12786 return 0;
12787 }
12788
12789 //start tile id
12790 if(!p_iputl(index,f))
12791 {
12792 return 0;
12793 }
12794
12795 //count
12796 if(!p_iputl(count,f))
12797 {
12798 return 0;
12799 }
12800 reset_combo_animations();
12801 reset_combo_animations2();
12802 size_t end = index+count;
12803 for(size_t q = index; q < end; ++q)
12804 {
12805 if(writecombo_loop(f, section_version, combobuf[q]))
12806 return 0;
12807 }
12808
12809 return 1;
12810
12811 }
12812
12813 //.ZALIAS
12814
12815
12816 //.ZALIAS
12817
12818 int32_t readcomboaliasfile(PACKFILE *f)
12819 {
12820 dword section_version=0;
12821 int32_t zversion = 0;
12822 int32_t zbuild = 0;
12823 word tempword = 0;
12824
12825 if(!p_igetl(&zversion,f))
12826 {
12827 return 0;
12828 }
12829 if(!p_igetl(&zbuild,f))
12830 {
12831 return 0;
12832 }
12833 if(!p_igetw(&section_version,f))
12834 {
12835 return 0;
12836 }
12837 if(!read_deprecated_section_cversion(f))
12838 {
12839 return 0;
12840 }
12841 al_trace("readoneweapon section_version: %d\n", section_version);
12842
12843 if ( zversion > ZELDA_VERSION )
12844 {
12845 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12846 return 0;
12847 }
12848
12849 else if ( ( section_version > V_COMBOALIASES ))
12850 {
12851 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
12852 return 0;
12853
12854 }
12855 else
12856 {
12857 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12858 }
12859
12860 int32_t index = 0;
12861 int32_t count = 0;
12862 int32_t count2 = 0;
12863 byte tempcset = 0;
12864
12865 //tile id
12866 if(!p_igetl(&index,f))
12867 {
12868 return 0;
12869 }
12870 al_trace("Reading combo: index(%d)\n", index);
12871
12872 //tile count
12873 if(!p_igetl(&count,f))
12874 {
12875 return 0;
12876 }
12877 al_trace("Reading combo: count(%d)\n", count);
12878
12879 combo_alias temp_alias;
12880
12881 for ( int32_t tilect = 0; tilect < count; tilect++ )
12882 {
12883 temp_alias.clear();
12884 if(!p_igetw(&temp_alias.combo,f))
12885 {
12886 return 0;
12887 }
12888
12889 if(!p_getc(&temp_alias.cset,f))
12890 {
12891 return 0;
12892 }
12893
12894
12895
12896 if(!p_igetl(&count2,f))
12897 {
12898 return 0;
12899 }
12900 al_trace("Read, Combo alias count is: %d\n", count2);
12901 if(!p_getc(&temp_alias.width,f))
12902 {
12903 return 0;
12904 }
12905
12906 if(!p_getc(&temp_alias.height,f))
12907 {
12908 return 0;
12909 }
12910
12911 if(!p_getc(&temp_alias.layermask,f))
12912 {
12913 return 0;
12914 }
12915 //These values are flexible, and may differ in size, so we delete them
12916 //and recreate them at the correct size on the pointer.
12917 temp_alias.combos.clear();
12918 temp_alias.csets.clear();
12919 for(int32_t k=0; k<count2; k++)
12920 {
12921 if(!p_igetw(&tempword,f))
12922 {
12923 return 0;
12924 }
12925 else
12926 {
12927
12928
12929 temp_alias.combos[k] = tempword;
12930 }
12931 }
12932
12933 for(int32_t k=0; k<count2; k++)
12934 {
12935 if(!p_getc(&tempcset,f))
12936 //if(!p_getc(&temp_alias.csets[k],f))
12937 {
12938 return 0;
12939 }
12940 else
12941 {
12942
12943 temp_alias.csets[k] = tempcset;
12944 }
12945 }
12946 combo_aliases[index+(tilect)] = temp_alias;
12947 }
12948
12949 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
12950
12951
12952 return 1;
12953
12954 }
12955
12956 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
12957 {
12958 dword section_version=0;
12959 int32_t zversion = 0;
12960 int32_t zbuild = 0;
12961
12962 if(!p_igetl(&zversion,f))
12963 {
12964 return 0;
12965 }
12966 if(!p_igetl(&zbuild,f))
12967 {
12968 return 0;
12969 }
12970 if(!p_igetw(&section_version,f))
12971 {
12972 return 0;
12973 }
12974 if(!read_deprecated_section_cversion(f))
12975 {
12976 return 0;
12977 }
12978 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
12979
12980 if ( zversion > ZELDA_VERSION )
12981 {
12982 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12983 return 0;
12984 }
12985 else if ( ( section_version > V_COMBOALIASES ))
12986 {
12987 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
12988 return 0;
12989
12990 }
12991 else
12992 {
12993 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12994 }
12995
12996 int32_t index = 0;
12997 int32_t count = 0;
12998 int32_t count2 = 0;
12999 byte tempcset = 0;
13000 word tempword = 0;
13001
13002
13003 //tile id
13004 if(!p_igetl(&index,f))
13005 {
13006 return 0;
13007 }
13008 al_trace("Reading tile: index(%d)\n", index);
13009
13010 //tile count
13011 if(!p_igetl(&count,f))
13012 {
13013 return 0;
13014 }
13015 al_trace("Reading tile: count(%d)\n", count);
13016
13017
13018 combo_alias temp_alias;
13019
13020 for ( int32_t tilect = 0; tilect < count; tilect++ )
13021 {
13022 temp_alias.clear();
13023 if(!p_igetw(&temp_alias.combo,f))
13024 {
13025 return 0;
13026 }
13027
13028 if(!p_getc(&temp_alias.cset,f))
13029 {
13030 return 0;
13031 }
13032
13033 int32_t count2 = 0;
13034
13035 if(!p_igetl(&count2,f))
13036 {
13037 return 0;
13038 }
13039
13040 if(!p_getc(&temp_alias.width,f))
13041 {
13042 return 0;
13043 }
13044
13045 if(!p_getc(&temp_alias.height,f))
13046 {
13047 return 0;
13048 }
13049
13050 if(!p_getc(&temp_alias.layermask,f))
13051 {
13052 return 0;
13053 }
13054 //These values are flexible, and may differ in size, so we delete them
13055 //and recreate them at the correct size on the pointer.
13056 temp_alias.combos.clear();
13057 temp_alias.csets.clear();
13058
13059 for(int32_t k=0; k<count2; k++)
13060 {
13061 if(!p_igetw(&tempword,f))
13062 {
13063 return 0;
13064 }
13065 else
13066 {
13067 temp_alias.combos[k] = tempword;
13068 }
13069 }
13070
13071 for(int32_t k=0; k<count2; k++)
13072 {
13073 if(!p_getc(&tempcset,f))
13074 {
13075 return 0;
13076 }
13077 else
13078 {
13079 temp_alias.csets[k] = tempcset;
13080 }
13081 }
13082
13083 if ( start+(tilect) < MAXCOMBOALIASES )
13084 {
13085 combo_aliases[start + (tilect)] = temp_alias;
13086 }
13087 }
13088 return 1;
13089 }
13090 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13091 {
13092 al_trace("Running writecomboaliasfile\n");
13093 dword section_version=V_COMBOALIASES;
13094 int32_t zversion = ZELDA_VERSION;
13095 int32_t zbuild = VERSION_BUILD;
13096
13097 if(!p_iputl(zversion,f))
13098 {
13099 return 0;
13100 }
13101 if(!p_iputl(zbuild,f))
13102 {
13103 return 0;
13104 }
13105 if(!p_iputw(section_version,f))
13106 {
13107 return 0;
13108 }
13109
13110 if(!write_deprecated_section_cversion(section_version,f))
13111 {
13112 return 0;
13113 }
13114
13115 //start tile id
13116 if(!p_iputl(index,f))
13117 {
13118 return 0;
13119 }
13120
13121 //count
13122 if(!p_iputl(count,f))
13123 {
13124 return 0;
13125 }
13126
13127 for ( int32_t tilect = 0; tilect < count; tilect++ )
13128 {
13129
13130 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13131 {
13132 return 0;
13133 }
13134
13135 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13136 {
13137 return 0;
13138 }
13139
13140 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13141
13142 if(!p_iputl(count2,f))
13143 {
13144 return 0;
13145 }
13146 al_trace("Write`, Combo alias count is: %d\n", count2);
13147
13148 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13149 {
13150 return 0;
13151 }
13152
13153 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13154 {
13155 return 0;
13156 }
13157
13158 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13159 {
13160 return 0;
13161 }
13162
13163 for(int32_t k=0; k<count2; k++)
13164 {
13165 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13166 {
13167 return 0;
13168 }
13169 }
13170
13171 for(int32_t k=0; k<count2; k++)
13172 {
13173 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13174 {
13175 return 0;
13176 }
13177 }
13178 }
13179
13180 return 1;
13181
13182 }
13183